Initial commit
This commit is contained in:
32
local_pod_repo/cmp/.gitignore
vendored
Normal file
32
local_pod_repo/cmp/.gitignore
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# OS X
|
||||
.DS_Store
|
||||
|
||||
# Xcode
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
profile
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
|
||||
# Bundler
|
||||
.bundle
|
||||
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
|
||||
#
|
||||
# Note: if you ignore the Pods directory, make sure to uncomment
|
||||
# `pod install` in .travis.yml
|
||||
#
|
||||
# Pods/
|
||||
22
local_pod_repo/cmp/LICENSE
Normal file
22
local_pod_repo/cmp/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
30
local_pod_repo/cmp/cmp.podspec
Normal file
30
local_pod_repo/cmp/cmp.podspec
Normal file
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# Be sure to run `pod lib lint toxcore.podspec' to ensure this is a
|
||||
# valid spec and remove all comments before submitting the spec.
|
||||
#
|
||||
# Any lines starting with a # are optional, but encouraged
|
||||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
|
||||
#
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "cmp"
|
||||
s.version = "20.0.0"
|
||||
s.summary = "Cocoapods wrapper for cmp"
|
||||
s.homepage = "https://github.com/camgunz/cmp"
|
||||
s.license = 'MIT'
|
||||
s.author = "Zoff"
|
||||
s.source = {
|
||||
:git => "https://github.com/camgunz/cmp.git",
|
||||
:tag => s.version.to_s,
|
||||
:submodules => true
|
||||
}
|
||||
|
||||
s.pod_target_xcconfig = { 'ENABLE_BITCODE' => 'NO', 'OTHER_LDFLAGS' => '-read_only_relocs suppress' }
|
||||
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.requires_arc = true
|
||||
|
||||
s.source_files = 'cmp/*h', 'cmp/*.c'
|
||||
|
||||
end
|
||||
54
local_pod_repo/cmp/cmp/.gitignore
vendored
Normal file
54
local_pod_repo/cmp/cmp/.gitignore
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Vim swap files
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Coverage files
|
||||
*.gcda
|
||||
*.gcno
|
||||
coverage/
|
||||
|
||||
# Profiling files
|
||||
*.prof
|
||||
|
||||
# Testing executable
|
||||
test/test-cmp
|
||||
cmptest
|
||||
cmptest2
|
||||
cmpaddrtest
|
||||
cmpmemtest
|
||||
cmpnofloattest
|
||||
cmpprof
|
||||
cmpubtest
|
||||
|
||||
# Example executables
|
||||
examples/example1
|
||||
examples/example2
|
||||
example1
|
||||
example2
|
||||
|
||||
# Test data
|
||||
cmp_data.dat
|
||||
4
local_pod_repo/cmp/cmp/CMakeLists.txt
Normal file
4
local_pod_repo/cmp/cmp/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
# Edit following two lines to set component requirements (see docs)
|
||||
set(COMPONENT_SRCS "cmp.c" )
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||
register_component()
|
||||
50
local_pod_repo/cmp/cmp/CODE_OF_CONDUCT.md
Normal file
50
local_pod_repo/cmp/cmp/CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of
|
||||
fostering an open and welcoming community, we pledge to respect all people who
|
||||
contribute through reporting issues, posting feature requests, updating
|
||||
documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free
|
||||
experience for everyone, regardless of level of experience, gender, gender
|
||||
identity and expression, sexual orientation, disability, personal appearance,
|
||||
body size, race, ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic
|
||||
addresses, without explicit permission
|
||||
* Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to
|
||||
fairly and consistently applying these principles to every aspect of managing
|
||||
this project. Project maintainers who do not follow or enforce the Code of
|
||||
Conduct may be permanently removed from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting a project maintainer at charles.gunyon@gmail.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. Maintainers are
|
||||
obligated to maintain confidentiality with regard to the reporter of an
|
||||
incident.
|
||||
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 1.3.0, available at
|
||||
[http://contributor-covenant.org/version/1/3/0/][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/3/0/
|
||||
22
local_pod_repo/cmp/cmp/LICENSE
Normal file
22
local_pod_repo/cmp/cmp/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
123
local_pod_repo/cmp/cmp/Makefile
Normal file
123
local_pod_repo/cmp/cmp/Makefile
Normal file
@@ -0,0 +1,123 @@
|
||||
CC ?= gcc
|
||||
CLANG ?= clang
|
||||
|
||||
EXTRA_CFLAGS ?= -Werror -Wall -Wextra -funsigned-char -fwrapv -Wconversion \
|
||||
-Wno-sign-conversion -Wmissing-format-attribute \
|
||||
-Wpointer-arith -Wformat-nonliteral -Winit-self \
|
||||
-Wwrite-strings -Wshadow -Wenum-compare -Wempty-body \
|
||||
-Wparentheses -Wcast-align -Wstrict-aliasing --pedantic-errors
|
||||
CMPCFLAGS ?= -std=c89 -Wno-c99-extensions
|
||||
TESTCFLAGS ?= -std=c99 -Wno-error=deprecated-declarations \
|
||||
-Wno-deprecated-declarations -O0
|
||||
NOFPUTESTCFLAGS ?= $(TESTCFLAGS) -DCMP_NO_FLOAT
|
||||
|
||||
ADDRCFLAGS ?= -fsanitize=address
|
||||
MEMCFLAGS ?= -fsanitize=memory -fno-omit-frame-pointer \
|
||||
-fno-optimize-sibling-calls
|
||||
UBCFLAGS ?= -fsanitize=undefined
|
||||
|
||||
.PHONY: all clean test coverage
|
||||
|
||||
all: cmpunittest example1 example2
|
||||
|
||||
profile: cmpprof
|
||||
@env LD_PRELOAD=/usr/lib/libprofiler.so CPUPROFILE=cmp.prof \
|
||||
CPUPROFILE_FREQUENCY=1000 ./cmpprof
|
||||
@pprof --web ./cmpprof cmp.prof
|
||||
|
||||
test: addrtest memtest nofloattest ubtest unittest
|
||||
|
||||
testprogs: cmpaddrtest cmpmemtest cmpnofloattest cmpubtest cmpunittest
|
||||
|
||||
addrtest: cmpaddrtest
|
||||
@./cmpaddrtest
|
||||
|
||||
memtest: cmpmemtest
|
||||
@./cmpmemtest
|
||||
|
||||
nofloattest: cmpnofloattest
|
||||
@./cmpnofloattest
|
||||
@rm -f *.gcno *.gcda *.info
|
||||
|
||||
ubtest: cmpubtest
|
||||
@./cmpubtest
|
||||
|
||||
unittest: cmpunittest
|
||||
@./cmpunittest
|
||||
|
||||
cmp.o: cmp.c
|
||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CMPCFLAGS) \
|
||||
-fprofile-arcs -ftest-coverage -g -I. -c cmp.c
|
||||
|
||||
cmpprof: cmp.o
|
||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(TESTCFLAGS) $(LDFLAGS) \
|
||||
-fprofile-arcs -I. \
|
||||
-o cmpprof cmp.o test/profile.c test/tests.c test/buf.c test/utils.c \
|
||||
-lcmocka -lprofiler
|
||||
|
||||
cmpunittest: cmp.o
|
||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(TESTCFLAGS) $(LDFLAGS) \
|
||||
-fprofile-arcs -ftest-coverage -g -I. \
|
||||
-o cmpunittest cmp.o test/test.c test/tests.c test/buf.c test/utils.c \
|
||||
-lcmocka
|
||||
|
||||
cmpnofloattest: cmp.o
|
||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(NOFPUTESTCFLAGS) $(LDFLAGS) \
|
||||
-fprofile-arcs -ftest-coverage -g -I. \
|
||||
-o cmpnofloattest cmp.o test/test.c test/tests.c test/buf.c \
|
||||
test/utils.c \
|
||||
-lcmocka
|
||||
|
||||
clangcmp.o: cmp.c
|
||||
$(CLANG) $(CFLAGS) $(EXTRA_CFLAGS) $(CMPCFLAGS) \
|
||||
-fprofile-arcs -ftest-coverage -g -I. -c cmp.c -o clangcmp.o
|
||||
|
||||
cmpaddrtest: clangcmp.o clean
|
||||
$(CLANG) $(CFLAGS) $(EXTRA_CFLAGS) $(TESTCFLAGS) $(ADDRCFLAGS) $(LDFLAGS) \
|
||||
-I. -o cmpaddrtest \
|
||||
cmp.c test/test.c test/tests.c test/buf.c test/utils.c \
|
||||
-lcmocka
|
||||
|
||||
cmpmemtest: clangcmp.o clean
|
||||
$(CLANG) $(CFLAGS) $(EXTRA_CFLAGS) $(TESTCFLAGS) $(MEMCFLAGS) $(LDFLAGS) \
|
||||
-I. -o cmpmemtest \
|
||||
cmp.c test/test.c test/tests.c test/buf.c test/utils.c \
|
||||
-lcmocka
|
||||
|
||||
cmpubtest: clangcmp.o clean
|
||||
$(CLANG) $(CFLAGS) $(EXTRA_CFLAGS) $(TESTCFLAGS) $(UBCFLAGS) $(LDFLAGS) \
|
||||
-I. -o cmpubtest \
|
||||
cmp.c test/test.c test/tests.c test/buf.c test/utils.c \
|
||||
-lcmocka
|
||||
|
||||
example1:
|
||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) --std=c89 -O3 -I. -o example1 \
|
||||
cmp.c examples/example1.c
|
||||
|
||||
example2:
|
||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) --std=c89 -O3 -I. -o example2 \
|
||||
cmp.c examples/example2.c
|
||||
|
||||
coverage:
|
||||
@rm -f base_coverage.info test_coverage.info total_coverage.info
|
||||
@rm -rf coverage
|
||||
@lcov -q -c -i -d . -o base_coverage.info
|
||||
@lcov -q -c -d . -o test_coverage.info
|
||||
@lcov -q -a base_coverage.info -a test_coverage.info -o total_coverage.info
|
||||
@lcov -q --summary total_coverage.info
|
||||
@mkdir coverage
|
||||
@genhtml -q -o coverage total_coverage.info
|
||||
|
||||
clean:
|
||||
@rm -f cmp.prof
|
||||
@rm -f cmpunittest
|
||||
@rm -f cmpaddrtest
|
||||
@rm -f cmpmemtest
|
||||
@rm -f cmpubtest
|
||||
@rm -f cmpnofloattest
|
||||
@rm -f cmpprof
|
||||
@rm -f example1
|
||||
@rm -f example2
|
||||
@rm -f *.o
|
||||
@rm -f *.gcno *.gcda *.info
|
||||
@rm -f cmp_data.dat
|
||||
223
local_pod_repo/cmp/cmp/README.md
Normal file
223
local_pod_repo/cmp/cmp/README.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# CMP
|
||||
|
||||
[](https://travis-ci.org/camgunz/cmp) [](https://coveralls.io/github/camgunz/cmp?branch=develop)
|
||||
|
||||
CMP is a C implementation of the MessagePack serialization format. It
|
||||
currently implements version 5 of the [MessagePack
|
||||
Spec](http://github.com/msgpack/msgpack/blob/master/spec.md).
|
||||
|
||||
CMP's goal is to be lightweight and straightforward, forcing nothing on the
|
||||
programmer.
|
||||
|
||||
## License
|
||||
|
||||
While I'm a big believer in the GPL, I license CMP under the MIT license.
|
||||
|
||||
## Example Usage
|
||||
|
||||
The following examples use a file as the backend, and are modeled after the
|
||||
examples included with the msgpack-c project.
|
||||
|
||||
```C
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
static bool read_bytes(void *data, size_t sz, FILE *fh) {
|
||||
return fread(data, sizeof(uint8_t), sz, fh) == (sz * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
static bool file_reader(cmp_ctx_t *ctx, void *data, size_t limit) {
|
||||
return read_bytes(data, limit, (FILE *)ctx->buf);
|
||||
}
|
||||
|
||||
static bool file_skipper(cmp_ctx_t *ctx, size_t count) {
|
||||
return fseek((FILE *)ctx->buf, count, SEEK_CUR);
|
||||
}
|
||||
|
||||
static size_t file_writer(cmp_ctx_t *ctx, const void *data, size_t count) {
|
||||
return fwrite(data, sizeof(uint8_t), count, (FILE *)ctx->buf);
|
||||
}
|
||||
|
||||
static void error_and_exit(const char *msg) {
|
||||
fprintf(stderr, "%s\n\n", msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
FILE *fh = NULL;
|
||||
cmp_ctx_t cmp = {0};
|
||||
uint32_t array_size = 0;
|
||||
uint32_t str_size = 0;
|
||||
char hello[6] = {0};
|
||||
char message_pack[12] = {0};
|
||||
|
||||
fh = fopen("cmp_data.dat", "w+b");
|
||||
|
||||
if (fh == NULL) {
|
||||
error_and_exit("Error opening data.dat");
|
||||
}
|
||||
|
||||
cmp_init(&cmp, fh, file_reader, file_skipper, file_writer);
|
||||
|
||||
if (!cmp_write_array(&cmp, 2)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_str(&cmp, "Hello", 5)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_str(&cmp, "MessagePack", 11)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
rewind(fh);
|
||||
|
||||
if (!cmp_read_array(&cmp, &array_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
/* You can read the str byte size and then read str bytes... */
|
||||
|
||||
if (!cmp_read_str_size(&cmp, &str_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (str_size > (sizeof(hello) - 1)) {
|
||||
error_and_exit("Packed 'hello' length too long\n");
|
||||
}
|
||||
|
||||
if (!read_bytes(hello, str_size, fh)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
/*
|
||||
* ...or you can set the maximum number of bytes to read and do it all in
|
||||
* one call
|
||||
*/
|
||||
|
||||
str_size = sizeof(message_pack);
|
||||
if (!cmp_read_str(&cmp, message_pack, &str_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
printf("Array Length: %u.\n", array_size);
|
||||
printf("[\"%s\", \"%s\"]\n", hello, message_pack);
|
||||
|
||||
fclose(fh);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
See the `examples` folder.
|
||||
|
||||
## Fast, Lightweight, Flexible, and Robust
|
||||
|
||||
CMP uses no internal buffers; conversions, encoding and decoding are done on
|
||||
the fly.
|
||||
|
||||
CMP's source and header file together are ~4k LOC.
|
||||
|
||||
CMP makes no heap allocations.
|
||||
|
||||
CMP uses standardized types rather than declaring its own, and it depends only
|
||||
on `stdbool.h`, `stdint.h` and `string.h`.
|
||||
|
||||
CMP is written using C89 (ANSI C), aside, of course, from its use of
|
||||
fixed-width integer types and `bool`.
|
||||
|
||||
On the other hand, CMP's test suite requires C99.
|
||||
|
||||
CMP only requires the programmer supply a read function, a write function, and
|
||||
an optional skip function. In this way, the programmer can use CMP on memory,
|
||||
files, sockets, etc.
|
||||
|
||||
CMP is portable. It uses fixed-width integer types, and checks the endianness
|
||||
of the machine at runtime before swapping bytes (MessagePack is big-endian).
|
||||
|
||||
CMP provides a fairly comprehensive error reporting mechanism modeled after
|
||||
`errno` and `strerror`.
|
||||
|
||||
CMP is thread aware; while contexts cannot be shared between threads, each
|
||||
thread may use its own context freely.
|
||||
|
||||
CMP is tested using the MessagePack test suite as well as a large set of custom
|
||||
test cases. Its small test program is compiled with clang using `-Wall -Werror
|
||||
-Wextra ...` along with several other flags, and generates no compilation
|
||||
errors in either clang or GCC.
|
||||
|
||||
CMP's source is written as readably as possible, using explicit, descriptive
|
||||
variable names and a consistent, clear style.
|
||||
|
||||
CMP's source is written to be as secure as possible. Its testing suite checks
|
||||
for invalid values, and data is always treated as suspect before it passes
|
||||
validation.
|
||||
|
||||
CMP's API is designed to be clear, convenient and unsurprising. Strings are
|
||||
null-terminated, binary data is not, error codes are clear, and so on.
|
||||
|
||||
CMP provides optional backwards compatibility for use with other MessagePack
|
||||
implementations that only implement version 4 of the spec.
|
||||
|
||||
## Building
|
||||
|
||||
There is no build system for CMP. The programmer can drop `cmp.c` and `cmp.h`
|
||||
in their source tree and modify as necessary. No special compiler settings are
|
||||
required to build it, and it generates no compilation errors in either clang or
|
||||
gcc.
|
||||
|
||||
## Versioning
|
||||
|
||||
CMP's versions are single integers. I don't use semantic versioning because
|
||||
I don't guarantee that any version is completely compatible with any other. In
|
||||
general, semantic versioning provides a false sense of security. You should be
|
||||
evaluating compatibility yourself, not relying on some stranger's versioning
|
||||
convention.
|
||||
|
||||
## Stability
|
||||
|
||||
I only guarantee stability for versions released on
|
||||
[the releases page](../../releases). While rare, both `master` and `develop`
|
||||
branches may have errors or mismatched versions.
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
Version 4 of the MessagePack spec has no `BIN` type, and provides no `STR8`
|
||||
marker. In order to remain backwards compatible with version 4 of MessagePack,
|
||||
do the following:
|
||||
|
||||
Avoid these functions:
|
||||
|
||||
- `cmp_write_bin`
|
||||
- `cmp_write_bin_marker`
|
||||
- `cmp_write_str8_marker`
|
||||
- `cmp_write_str8`
|
||||
- `cmp_write_bin8_marker`
|
||||
- `cmp_write_bin8`
|
||||
- `cmp_write_bin16_marker`
|
||||
- `cmp_write_bin16`
|
||||
- `cmp_write_bin32_marker`
|
||||
- `cmp_write_bin32`
|
||||
|
||||
Use these functions in lieu of their v5 counterparts:
|
||||
|
||||
- `cmp_write_str_marker_v4` instead of `cmp_write_str_marker`
|
||||
- `cmp_write_str_v4` instead of `cmp_write_str`
|
||||
- `cmp_write_object_v4` instead of `cmp_write_object`
|
||||
|
||||
## Disabling Floating Point Operations
|
||||
|
||||
Thanks to [tdragon](https://github.com/tdragon) it's possible to disable
|
||||
floating point operations in CMP by defining `CMP_NO_FLOAT`. No floating point
|
||||
functionality will be included. Fair warning: this changes the ABI.
|
||||
|
||||
## Setting Endianness at Compile Time
|
||||
|
||||
CMP will honor `WORDS_BIGENDIAN`. If defined to `0` it will convert data
|
||||
to/from little-endian format when writing/reading. If defined to `1` it won't.
|
||||
If not defined, CMP will check at runtime.
|
||||
14
local_pod_repo/cmp/cmp/TODO.md
Normal file
14
local_pod_repo/cmp/cmp/TODO.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# To Do
|
||||
|
||||
- Work on fixing double-copy issue
|
||||
- Essentially everything is written to a `cmp_object_t` before it's written
|
||||
out to the caller, which is inefficient. The reasoning for this is to not
|
||||
pollute the caller's environment should an error occur, but in practice
|
||||
it's probably better to say, "you can't trust the contents of output
|
||||
arguments you pass to CMP if the call fails".
|
||||
|
||||
- Build real docs
|
||||
- Probably still just a Markdown file, but still, things have gotten complex
|
||||
enough that `cmp.h` and `README.md` don't really cover it anymore.
|
||||
|
||||
- Prevent users from using extended types < 0 (reserved by MessagePack)
|
||||
3561
local_pod_repo/cmp/cmp/cmp.c
Normal file
3561
local_pod_repo/cmp/cmp/cmp.c
Normal file
File diff suppressed because it is too large
Load Diff
572
local_pod_repo/cmp/cmp/cmp.h
Normal file
572
local_pod_repo/cmp/cmp/cmp.h
Normal file
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CMP_H_INCLUDED
|
||||
#define CMP_H_INCLUDED
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct cmp_ctx_s;
|
||||
|
||||
typedef bool (*cmp_reader)(struct cmp_ctx_s *ctx, void *data, size_t limit);
|
||||
typedef bool (*cmp_skipper)(struct cmp_ctx_s *ctx, size_t count);
|
||||
typedef size_t (*cmp_writer)(struct cmp_ctx_s *ctx, const void *data,
|
||||
size_t count);
|
||||
|
||||
enum {
|
||||
CMP_TYPE_POSITIVE_FIXNUM, /* 0 */
|
||||
CMP_TYPE_FIXMAP, /* 1 */
|
||||
CMP_TYPE_FIXARRAY, /* 2 */
|
||||
CMP_TYPE_FIXSTR, /* 3 */
|
||||
CMP_TYPE_NIL, /* 4 */
|
||||
CMP_TYPE_BOOLEAN, /* 5 */
|
||||
CMP_TYPE_BIN8, /* 6 */
|
||||
CMP_TYPE_BIN16, /* 7 */
|
||||
CMP_TYPE_BIN32, /* 8 */
|
||||
CMP_TYPE_EXT8, /* 9 */
|
||||
CMP_TYPE_EXT16, /* 10 */
|
||||
CMP_TYPE_EXT32, /* 11 */
|
||||
CMP_TYPE_FLOAT, /* 12 */
|
||||
CMP_TYPE_DOUBLE, /* 13 */
|
||||
CMP_TYPE_UINT8, /* 14 */
|
||||
CMP_TYPE_UINT16, /* 15 */
|
||||
CMP_TYPE_UINT32, /* 16 */
|
||||
CMP_TYPE_UINT64, /* 17 */
|
||||
CMP_TYPE_SINT8, /* 18 */
|
||||
CMP_TYPE_SINT16, /* 19 */
|
||||
CMP_TYPE_SINT32, /* 20 */
|
||||
CMP_TYPE_SINT64, /* 21 */
|
||||
CMP_TYPE_FIXEXT1, /* 22 */
|
||||
CMP_TYPE_FIXEXT2, /* 23 */
|
||||
CMP_TYPE_FIXEXT4, /* 24 */
|
||||
CMP_TYPE_FIXEXT8, /* 25 */
|
||||
CMP_TYPE_FIXEXT16, /* 26 */
|
||||
CMP_TYPE_STR8, /* 27 */
|
||||
CMP_TYPE_STR16, /* 28 */
|
||||
CMP_TYPE_STR32, /* 29 */
|
||||
CMP_TYPE_ARRAY16, /* 30 */
|
||||
CMP_TYPE_ARRAY32, /* 31 */
|
||||
CMP_TYPE_MAP16, /* 32 */
|
||||
CMP_TYPE_MAP32, /* 33 */
|
||||
CMP_TYPE_NEGATIVE_FIXNUM /* 34 */
|
||||
};
|
||||
|
||||
typedef struct cmp_ext_s {
|
||||
int8_t type;
|
||||
uint32_t size;
|
||||
} cmp_ext_t;
|
||||
|
||||
union cmp_object_data_u {
|
||||
bool boolean;
|
||||
uint8_t u8;
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
int8_t s8;
|
||||
int16_t s16;
|
||||
int32_t s32;
|
||||
int64_t s64;
|
||||
#ifndef CMP_NO_FLOAT
|
||||
float flt;
|
||||
double dbl;
|
||||
#endif /* CMP_NO_FLOAT */
|
||||
uint32_t array_size;
|
||||
uint32_t map_size;
|
||||
uint32_t str_size;
|
||||
uint32_t bin_size;
|
||||
cmp_ext_t ext;
|
||||
};
|
||||
|
||||
typedef struct cmp_ctx_s {
|
||||
uint8_t error;
|
||||
void *buf;
|
||||
cmp_reader read;
|
||||
cmp_skipper skip;
|
||||
cmp_writer write;
|
||||
} cmp_ctx_t;
|
||||
|
||||
typedef struct cmp_object_s {
|
||||
uint8_t type;
|
||||
union cmp_object_data_u as;
|
||||
} cmp_object_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* === Main API
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initializes a CMP context
|
||||
*
|
||||
* If you don't intend to read, `read` may be NULL, but calling `*read*`
|
||||
* functions will crash; there is no check.
|
||||
*
|
||||
* `skip` may be NULL, in which case skipping functions will use `read`.
|
||||
*
|
||||
* If you don't intend to write, `write` may be NULL, but calling `*write*`
|
||||
* functions will crash; there is no check.
|
||||
*/
|
||||
void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader read,
|
||||
cmp_skipper skip,
|
||||
cmp_writer write);
|
||||
|
||||
/* Returns CMP's version */
|
||||
uint32_t cmp_version(void);
|
||||
|
||||
/* Returns the MessagePack version employed by CMP */
|
||||
uint32_t cmp_mp_version(void);
|
||||
|
||||
/* Returns a string description of a CMP context's error */
|
||||
const char* cmp_strerror(cmp_ctx_t *ctx);
|
||||
|
||||
/* Writes a signed integer to the backend */
|
||||
bool cmp_write_integer(cmp_ctx_t *ctx, int64_t d);
|
||||
|
||||
/* Writes an unsigned integer to the backend */
|
||||
bool cmp_write_uinteger(cmp_ctx_t *ctx, uint64_t u);
|
||||
|
||||
/*
|
||||
* Writes a floating-point value (either single or double-precision) to the
|
||||
* backend
|
||||
*/
|
||||
#ifndef CMP_NO_FLOAT
|
||||
bool cmp_write_decimal(cmp_ctx_t *ctx, double d);
|
||||
#endif /* CMP_NO_FLOAT */
|
||||
|
||||
/* Writes NULL to the backend */
|
||||
bool cmp_write_nil(cmp_ctx_t *ctx);
|
||||
|
||||
/* Writes true to the backend */
|
||||
bool cmp_write_true(cmp_ctx_t *ctx);
|
||||
|
||||
/* Writes false to the backend */
|
||||
bool cmp_write_false(cmp_ctx_t *ctx);
|
||||
|
||||
/* Writes a boolean value to the backend */
|
||||
bool cmp_write_bool(cmp_ctx_t *ctx, bool b);
|
||||
|
||||
/*
|
||||
* Writes an unsigned char's value to the backend as a boolean. This is useful
|
||||
* if you are using a different boolean type in your application.
|
||||
*/
|
||||
bool cmp_write_u8_as_bool(cmp_ctx_t *ctx, uint8_t b);
|
||||
|
||||
/*
|
||||
* Writes a string to the backend; according to the MessagePack spec, this must
|
||||
* be encoded using UTF-8, but CMP leaves that job up to the programmer.
|
||||
*/
|
||||
bool cmp_write_str(cmp_ctx_t *ctx, const char *data, uint32_t size);
|
||||
|
||||
/*
|
||||
* Writes a string to the backend. This avoids using the STR8 marker, which
|
||||
* is unsupported by MessagePack v4, the version implemented by many other
|
||||
* MessagePack libraries. No encoding is assumed in this case, not that it
|
||||
* matters.
|
||||
*/
|
||||
bool cmp_write_str_v4(cmp_ctx_t *ctx, const char *data, uint32_t size);
|
||||
|
||||
/*
|
||||
* Writes the string marker to the backend. This is useful if you are writing
|
||||
* data in chunks instead of a single shot.
|
||||
*/
|
||||
bool cmp_write_str_marker(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
/*
|
||||
* Writes the string marker to the backend. This is useful if you are writing
|
||||
* data in chunks instead of a single shot. This avoids using the STR8
|
||||
* marker, which is unsupported by MessagePack v4, the version implemented by
|
||||
* many other MessagePack libraries. No encoding is assumed in this case, not
|
||||
* that it matters.
|
||||
*/
|
||||
bool cmp_write_str_marker_v4(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
/* Writes binary data to the backend */
|
||||
bool cmp_write_bin(cmp_ctx_t *ctx, const void *data, uint32_t size);
|
||||
|
||||
/*
|
||||
* Writes the binary data marker to the backend. This is useful if you are
|
||||
* writing data in chunks instead of a single shot.
|
||||
*/
|
||||
bool cmp_write_bin_marker(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
/* Writes an array to the backend. */
|
||||
bool cmp_write_array(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
/* Writes a map to the backend. */
|
||||
bool cmp_write_map(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
/* Writes an extended type to the backend */
|
||||
bool cmp_write_ext(cmp_ctx_t *ctx, int8_t type, uint32_t size,
|
||||
const void *data);
|
||||
|
||||
/*
|
||||
* Writes the extended type marker to the backend. This is useful if you want
|
||||
* to write the type's data in chunks instead of a single shot.
|
||||
*/
|
||||
bool cmp_write_ext_marker(cmp_ctx_t *ctx, int8_t type, uint32_t size);
|
||||
|
||||
/* Writes an object to the backend */
|
||||
bool cmp_write_object(cmp_ctx_t *ctx, const cmp_object_t *obj);
|
||||
|
||||
/*
|
||||
* Writes an object to the backend. This avoids using the STR8 marker, which
|
||||
* is unsupported by MessagePack v4, the version implemented by many other
|
||||
* MessagePack libraries.
|
||||
*/
|
||||
bool cmp_write_object_v4(cmp_ctx_t *ctx, const cmp_object_t *obj);
|
||||
|
||||
/* Reads a signed integer that fits inside a signed char */
|
||||
bool cmp_read_char(cmp_ctx_t *ctx, int8_t *c);
|
||||
|
||||
/* Reads a signed integer that fits inside a signed short */
|
||||
bool cmp_read_short(cmp_ctx_t *ctx, int16_t *s);
|
||||
|
||||
/* Reads a signed integer that fits inside a signed int */
|
||||
bool cmp_read_int(cmp_ctx_t *ctx, int32_t *i);
|
||||
|
||||
/* Reads a signed integer that fits inside a signed long */
|
||||
bool cmp_read_long(cmp_ctx_t *ctx, int64_t *d);
|
||||
|
||||
/* Reads a signed integer */
|
||||
bool cmp_read_integer(cmp_ctx_t *ctx, int64_t *d);
|
||||
|
||||
/* Reads an unsigned integer that fits inside an unsigned char */
|
||||
bool cmp_read_uchar(cmp_ctx_t *ctx, uint8_t *c);
|
||||
|
||||
/* Reads an unsigned integer that fits inside an unsigned short */
|
||||
bool cmp_read_ushort(cmp_ctx_t *ctx, uint16_t *s);
|
||||
|
||||
/* Reads an unsigned integer that fits inside an unsigned int */
|
||||
bool cmp_read_uint(cmp_ctx_t *ctx, uint32_t *i);
|
||||
|
||||
/* Reads an unsigned integer that fits inside an unsigned long */
|
||||
bool cmp_read_ulong(cmp_ctx_t *ctx, uint64_t *u);
|
||||
|
||||
/* Reads an unsigned integer */
|
||||
bool cmp_read_uinteger(cmp_ctx_t *ctx, uint64_t *u);
|
||||
|
||||
/*
|
||||
* Reads a floating point value (either single or double-precision) from the
|
||||
* backend
|
||||
*/
|
||||
#ifndef CMP_NO_FLOAT
|
||||
bool cmp_read_decimal(cmp_ctx_t *ctx, double *d);
|
||||
#endif /* CMP_NO_FLOAT */
|
||||
|
||||
/* "Reads" (more like "skips") a NULL value from the backend */
|
||||
bool cmp_read_nil(cmp_ctx_t *ctx);
|
||||
|
||||
/* Reads a boolean from the backend */
|
||||
bool cmp_read_bool(cmp_ctx_t *ctx, bool *b);
|
||||
|
||||
/*
|
||||
* Reads a boolean as an unsigned char from the backend; this is useful if your
|
||||
* application uses a different boolean type.
|
||||
*/
|
||||
bool cmp_read_bool_as_u8(cmp_ctx_t *ctx, uint8_t *b);
|
||||
|
||||
/* Reads a string's size from the backend */
|
||||
bool cmp_read_str_size(cmp_ctx_t *ctx, uint32_t *size);
|
||||
|
||||
/*
|
||||
* Reads a string from the backend; according to the spec, the string's data
|
||||
* ought to be encoded using UTF-8, but CMP leaves that job up to the programmer.
|
||||
*/
|
||||
bool cmp_read_str(cmp_ctx_t *ctx, char *data, uint32_t *size);
|
||||
|
||||
/* Reads the size of packed binary data from the backend */
|
||||
bool cmp_read_bin_size(cmp_ctx_t *ctx, uint32_t *size);
|
||||
|
||||
/* Reads packed binary data from the backend */
|
||||
bool cmp_read_bin(cmp_ctx_t *ctx, void *data, uint32_t *size);
|
||||
|
||||
/* Reads an array from the backend */
|
||||
bool cmp_read_array(cmp_ctx_t *ctx, uint32_t *size);
|
||||
|
||||
/* Reads a map from the backend */
|
||||
bool cmp_read_map(cmp_ctx_t *ctx, uint32_t *size);
|
||||
|
||||
/* Reads the extended type's marker from the backend */
|
||||
bool cmp_read_ext_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size);
|
||||
|
||||
/* Reads an extended type from the backend */
|
||||
bool cmp_read_ext(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data);
|
||||
|
||||
/* Reads an object from the backend */
|
||||
bool cmp_read_object(cmp_ctx_t *ctx, cmp_object_t *obj);
|
||||
|
||||
/*
|
||||
* Skips the next object from the backend. If that object is an array or map,
|
||||
* this function will:
|
||||
* - If `obj` is not `NULL`, fill in `obj` with that object
|
||||
* - Set `ctx->error` to `SKIP_DEPTH_LIMIT_EXCEEDED_ERROR`
|
||||
* - Return `false`
|
||||
* Otherwise:
|
||||
* - (Don't touch `obj`)
|
||||
* - Return `true`
|
||||
*/
|
||||
bool cmp_skip_object(cmp_ctx_t *ctx, cmp_object_t *obj);
|
||||
|
||||
/*
|
||||
* This is similar to `cmp_skip_object`, except it tolerates flat arrays and
|
||||
* maps. If when skipping such an array or map this function encounters
|
||||
* another array/map, it will:
|
||||
* - If `obj` is not `NULL`, fill in `obj` with that (nested) object
|
||||
* - Set `ctx->error` to `SKIP_DEPTH_LIMIT_EXCEEDED_ERROR`
|
||||
* - Return `false`
|
||||
* Otherwise:
|
||||
* - (Don't touch `obj`)
|
||||
* - Return `true`
|
||||
*
|
||||
* WARNING: This can cause your application to spend an unbounded amount of
|
||||
* time reading nested data structures. Unless you completely trust
|
||||
* the data source, you should use `cmp_skip_object`.
|
||||
*/
|
||||
bool cmp_skip_object_flat(cmp_ctx_t *ctx, cmp_object_t *obj);
|
||||
|
||||
/*
|
||||
* This is similar to `cmp_skip_object`, except it will continually skip
|
||||
* nested data structures.
|
||||
*
|
||||
* WARNING: This can cause your application to spend an unbounded amount of
|
||||
* time reading nested data structures. Unless you completely trust
|
||||
* the data source, you should use `cmp_skip_object`.
|
||||
*/
|
||||
bool cmp_skip_object_no_limit(cmp_ctx_t *ctx);
|
||||
|
||||
/*
|
||||
* WARNING: THIS FUNCTION IS DEPRECATED AND WILL BE REMOVED IN A FUTURE RELEASE
|
||||
*
|
||||
* There is no way to track depths across elements without allocation. For
|
||||
* example, an array constructed as: `[ [] [] [] [] [] [] [] [] [] [] ]`
|
||||
* should be able to be skipped with `cmp_skip_object_limit(&cmp, &obj, 2)`.
|
||||
* However, because we cannot track depth across the elements, there's no way
|
||||
* to reset it after descending down into each element.
|
||||
*
|
||||
* This is similar to `cmp_skip_object`, except it tolerates up to `limit`
|
||||
* levels of nesting. For example, in order to skip an array that contains a
|
||||
* map, call `cmp_skip_object_limit(ctx, &obj, 2)`. Or in other words,
|
||||
* `cmp_skip_object(ctx, &obj)` acts similarly to `cmp_skip_object_limit(ctx,
|
||||
* &obj, 0)`
|
||||
*
|
||||
* Specifically, `limit` refers to depth, not breadth. So in order to skip an
|
||||
* array that contains two arrays that each contain 3 strings, you would call
|
||||
* `cmp_skip_object_limit(ctx, &obj, 2). In order to skip an array that
|
||||
* contains 4 arrays that each contain 1 string, you would still call
|
||||
* `cmp_skip_object_limit(ctx, &obj, 2).
|
||||
*/
|
||||
bool cmp_skip_object_limit(cmp_ctx_t *ctx, cmp_object_t *obj, uint32_t limit)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((deprecated))
|
||||
#endif
|
||||
;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma deprecated(cmp_skip_object_limit)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* === Specific API
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
bool cmp_write_pfix(cmp_ctx_t *ctx, uint8_t c);
|
||||
bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c);
|
||||
|
||||
bool cmp_write_sfix(cmp_ctx_t *ctx, int8_t c);
|
||||
bool cmp_write_s8(cmp_ctx_t *ctx, int8_t c);
|
||||
bool cmp_write_s16(cmp_ctx_t *ctx, int16_t s);
|
||||
bool cmp_write_s32(cmp_ctx_t *ctx, int32_t i);
|
||||
bool cmp_write_s64(cmp_ctx_t *ctx, int64_t l);
|
||||
|
||||
bool cmp_write_ufix(cmp_ctx_t *ctx, uint8_t c);
|
||||
bool cmp_write_u8(cmp_ctx_t *ctx, uint8_t c);
|
||||
bool cmp_write_u16(cmp_ctx_t *ctx, uint16_t s);
|
||||
bool cmp_write_u32(cmp_ctx_t *ctx, uint32_t i);
|
||||
bool cmp_write_u64(cmp_ctx_t *ctx, uint64_t l);
|
||||
|
||||
#ifndef CMP_NO_FLOAT
|
||||
bool cmp_write_float(cmp_ctx_t *ctx, float f);
|
||||
bool cmp_write_double(cmp_ctx_t *ctx, double d);
|
||||
#endif /* CMP_NO_FLOAT */
|
||||
|
||||
bool cmp_write_fixstr_marker(cmp_ctx_t *ctx, uint8_t size);
|
||||
bool cmp_write_fixstr(cmp_ctx_t *ctx, const char *data, uint8_t size);
|
||||
bool cmp_write_str8_marker(cmp_ctx_t *ctx, uint8_t size);
|
||||
bool cmp_write_str8(cmp_ctx_t *ctx, const char *data, uint8_t size);
|
||||
bool cmp_write_str16_marker(cmp_ctx_t *ctx, uint16_t size);
|
||||
bool cmp_write_str16(cmp_ctx_t *ctx, const char *data, uint16_t size);
|
||||
bool cmp_write_str32_marker(cmp_ctx_t *ctx, uint32_t size);
|
||||
bool cmp_write_str32(cmp_ctx_t *ctx, const char *data, uint32_t size);
|
||||
|
||||
bool cmp_write_bin8_marker(cmp_ctx_t *ctx, uint8_t size);
|
||||
bool cmp_write_bin8(cmp_ctx_t *ctx, const void *data, uint8_t size);
|
||||
bool cmp_write_bin16_marker(cmp_ctx_t *ctx, uint16_t size);
|
||||
bool cmp_write_bin16(cmp_ctx_t *ctx, const void *data, uint16_t size);
|
||||
bool cmp_write_bin32_marker(cmp_ctx_t *ctx, uint32_t size);
|
||||
bool cmp_write_bin32(cmp_ctx_t *ctx, const void *data, uint32_t size);
|
||||
|
||||
bool cmp_write_fixarray(cmp_ctx_t *ctx, uint8_t size);
|
||||
bool cmp_write_array16(cmp_ctx_t *ctx, uint16_t size);
|
||||
bool cmp_write_array32(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
bool cmp_write_fixmap(cmp_ctx_t *ctx, uint8_t size);
|
||||
bool cmp_write_map16(cmp_ctx_t *ctx, uint16_t size);
|
||||
bool cmp_write_map32(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
bool cmp_write_fixext1_marker(cmp_ctx_t *ctx, int8_t type);
|
||||
bool cmp_write_fixext1(cmp_ctx_t *ctx, int8_t type, const void *data);
|
||||
bool cmp_write_fixext2_marker(cmp_ctx_t *ctx, int8_t type);
|
||||
bool cmp_write_fixext2(cmp_ctx_t *ctx, int8_t type, const void *data);
|
||||
bool cmp_write_fixext4_marker(cmp_ctx_t *ctx, int8_t type);
|
||||
bool cmp_write_fixext4(cmp_ctx_t *ctx, int8_t type, const void *data);
|
||||
bool cmp_write_fixext8_marker(cmp_ctx_t *ctx, int8_t type);
|
||||
bool cmp_write_fixext8(cmp_ctx_t *ctx, int8_t type, const void *data);
|
||||
bool cmp_write_fixext16_marker(cmp_ctx_t *ctx, int8_t type);
|
||||
bool cmp_write_fixext16(cmp_ctx_t *ctx, int8_t type, const void *data);
|
||||
|
||||
bool cmp_write_ext8_marker(cmp_ctx_t *ctx, int8_t type, uint8_t size);
|
||||
bool cmp_write_ext8(cmp_ctx_t *ctx, int8_t type, uint8_t size,
|
||||
const void *data);
|
||||
bool cmp_write_ext16_marker(cmp_ctx_t *ctx, int8_t type, uint16_t size);
|
||||
bool cmp_write_ext16(cmp_ctx_t *ctx, int8_t type, uint16_t size,
|
||||
const void *data);
|
||||
bool cmp_write_ext32_marker(cmp_ctx_t *ctx, int8_t type, uint32_t size);
|
||||
bool cmp_write_ext32(cmp_ctx_t *ctx, int8_t type, uint32_t size,
|
||||
const void *data);
|
||||
|
||||
bool cmp_read_pfix(cmp_ctx_t *ctx, uint8_t *c);
|
||||
bool cmp_read_nfix(cmp_ctx_t *ctx, int8_t *c);
|
||||
|
||||
bool cmp_read_sfix(cmp_ctx_t *ctx, int8_t *c);
|
||||
bool cmp_read_s8(cmp_ctx_t *ctx, int8_t *c);
|
||||
bool cmp_read_s16(cmp_ctx_t *ctx, int16_t *s);
|
||||
bool cmp_read_s32(cmp_ctx_t *ctx, int32_t *i);
|
||||
bool cmp_read_s64(cmp_ctx_t *ctx, int64_t *l);
|
||||
|
||||
bool cmp_read_ufix(cmp_ctx_t *ctx, uint8_t *c);
|
||||
bool cmp_read_u8(cmp_ctx_t *ctx, uint8_t *c);
|
||||
bool cmp_read_u16(cmp_ctx_t *ctx, uint16_t *s);
|
||||
bool cmp_read_u32(cmp_ctx_t *ctx, uint32_t *i);
|
||||
bool cmp_read_u64(cmp_ctx_t *ctx, uint64_t *l);
|
||||
|
||||
#ifndef CMP_NO_FLOAT
|
||||
bool cmp_read_float(cmp_ctx_t *ctx, float *f);
|
||||
bool cmp_read_double(cmp_ctx_t *ctx, double *d);
|
||||
#endif /* CMP_NO_FLOAT */
|
||||
|
||||
bool cmp_read_fixext1_marker(cmp_ctx_t *ctx, int8_t *type);
|
||||
bool cmp_read_fixext1(cmp_ctx_t *ctx, int8_t *type, void *data);
|
||||
bool cmp_read_fixext2_marker(cmp_ctx_t *ctx, int8_t *type);
|
||||
bool cmp_read_fixext2(cmp_ctx_t *ctx, int8_t *type, void *data);
|
||||
bool cmp_read_fixext4_marker(cmp_ctx_t *ctx, int8_t *type);
|
||||
bool cmp_read_fixext4(cmp_ctx_t *ctx, int8_t *type, void *data);
|
||||
bool cmp_read_fixext8_marker(cmp_ctx_t *ctx, int8_t *type);
|
||||
bool cmp_read_fixext8(cmp_ctx_t *ctx, int8_t *type, void *data);
|
||||
bool cmp_read_fixext16_marker(cmp_ctx_t *ctx, int8_t *type);
|
||||
bool cmp_read_fixext16(cmp_ctx_t *ctx, int8_t *type, void *data);
|
||||
|
||||
bool cmp_read_ext8_marker(cmp_ctx_t *ctx, int8_t *type, uint8_t *size);
|
||||
bool cmp_read_ext8(cmp_ctx_t *ctx, int8_t *type, uint8_t *size, void *data);
|
||||
bool cmp_read_ext16_marker(cmp_ctx_t *ctx, int8_t *type, uint16_t *size);
|
||||
bool cmp_read_ext16(cmp_ctx_t *ctx, int8_t *type, uint16_t *size, void *data);
|
||||
bool cmp_read_ext32_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size);
|
||||
bool cmp_read_ext32(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data);
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* === Object API
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
bool cmp_object_is_char(const cmp_object_t *obj);
|
||||
bool cmp_object_is_short(const cmp_object_t *obj);
|
||||
bool cmp_object_is_int(const cmp_object_t *obj);
|
||||
bool cmp_object_is_long(const cmp_object_t *obj);
|
||||
bool cmp_object_is_sinteger(const cmp_object_t *obj);
|
||||
bool cmp_object_is_uchar(const cmp_object_t *obj);
|
||||
bool cmp_object_is_ushort(const cmp_object_t *obj);
|
||||
bool cmp_object_is_uint(const cmp_object_t *obj);
|
||||
bool cmp_object_is_ulong(const cmp_object_t *obj);
|
||||
bool cmp_object_is_uinteger(const cmp_object_t *obj);
|
||||
bool cmp_object_is_float(const cmp_object_t *obj);
|
||||
bool cmp_object_is_double(const cmp_object_t *obj);
|
||||
bool cmp_object_is_nil(const cmp_object_t *obj);
|
||||
bool cmp_object_is_bool(const cmp_object_t *obj);
|
||||
bool cmp_object_is_str(const cmp_object_t *obj);
|
||||
bool cmp_object_is_bin(const cmp_object_t *obj);
|
||||
bool cmp_object_is_array(const cmp_object_t *obj);
|
||||
bool cmp_object_is_map(const cmp_object_t *obj);
|
||||
bool cmp_object_is_ext(const cmp_object_t *obj);
|
||||
|
||||
bool cmp_object_as_char(const cmp_object_t *obj, int8_t *c);
|
||||
bool cmp_object_as_short(const cmp_object_t *obj, int16_t *s);
|
||||
bool cmp_object_as_int(const cmp_object_t *obj, int32_t *i);
|
||||
bool cmp_object_as_long(const cmp_object_t *obj, int64_t *d);
|
||||
bool cmp_object_as_sinteger(const cmp_object_t *obj, int64_t *d);
|
||||
bool cmp_object_as_uchar(const cmp_object_t *obj, uint8_t *c);
|
||||
bool cmp_object_as_ushort(const cmp_object_t *obj, uint16_t *s);
|
||||
bool cmp_object_as_uint(const cmp_object_t *obj, uint32_t *i);
|
||||
bool cmp_object_as_ulong(const cmp_object_t *obj, uint64_t *u);
|
||||
bool cmp_object_as_uinteger(const cmp_object_t *obj, uint64_t *u);
|
||||
bool cmp_object_as_float(const cmp_object_t *obj, float *f);
|
||||
bool cmp_object_as_double(const cmp_object_t *obj, double *d);
|
||||
bool cmp_object_as_bool(const cmp_object_t *obj, bool *b);
|
||||
bool cmp_object_as_str(const cmp_object_t *obj, uint32_t *size);
|
||||
bool cmp_object_as_bin(const cmp_object_t *obj, uint32_t *size);
|
||||
bool cmp_object_as_array(const cmp_object_t *obj, uint32_t *size);
|
||||
bool cmp_object_as_map(const cmp_object_t *obj, uint32_t *size);
|
||||
bool cmp_object_as_ext(const cmp_object_t *obj, int8_t *type, uint32_t *size);
|
||||
|
||||
bool cmp_object_to_str(cmp_ctx_t *ctx, const cmp_object_t *obj, char *data, uint32_t buf_size);
|
||||
bool cmp_object_to_bin(cmp_ctx_t *ctx, const cmp_object_t *obj, void *data, uint32_t buf_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* === Backwards compatibility defines
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
#define cmp_write_int cmp_write_integer
|
||||
#define cmp_write_sint cmp_write_integer
|
||||
#define cmp_write_sinteger cmp_write_integer
|
||||
#define cmp_write_uint cmp_write_uinteger
|
||||
#define cmp_read_sinteger cmp_read_integer
|
||||
|
||||
#endif /* CMP_H_INCLUDED */
|
||||
|
||||
/* vi: set et ts=2 sw=2: */
|
||||
|
||||
116
local_pod_repo/cmp/cmp/examples/example1.c
Normal file
116
local_pod_repo/cmp/cmp/examples/example1.c
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
static bool read_bytes(void *data, size_t sz, FILE *fh) {
|
||||
return fread(data, sizeof(uint8_t), sz, fh) == (sz * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
static bool file_reader(cmp_ctx_t *ctx, void *data, size_t limit) {
|
||||
return read_bytes(data, limit, (FILE *)ctx->buf);
|
||||
}
|
||||
|
||||
static bool file_skipper(cmp_ctx_t *ctx, size_t count) {
|
||||
return fseek((FILE *)ctx->buf, count, SEEK_CUR);
|
||||
}
|
||||
|
||||
static size_t file_writer(cmp_ctx_t *ctx, const void *data, size_t count) {
|
||||
return fwrite(data, sizeof(uint8_t), count, (FILE *)ctx->buf);
|
||||
}
|
||||
|
||||
static void error_and_exit(const char *msg) {
|
||||
fprintf(stderr, "%s\n\n", msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
FILE *fh = NULL;
|
||||
cmp_ctx_t cmp = {0};
|
||||
uint32_t array_size = 0;
|
||||
uint32_t str_size = 0;
|
||||
char hello[6] = {0};
|
||||
char message_pack[12] = {0};
|
||||
|
||||
fh = fopen("cmp_data.dat", "w+b");
|
||||
|
||||
if (fh == NULL) {
|
||||
error_and_exit("Error opening data.dat");
|
||||
}
|
||||
|
||||
cmp_init(&cmp, fh, file_reader, file_skipper, file_writer);
|
||||
|
||||
if (!cmp_write_array(&cmp, 2)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_str(&cmp, "Hello", 5)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_str(&cmp, "MessagePack", 11)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
rewind(fh);
|
||||
|
||||
if (!cmp_read_array(&cmp, &array_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
/* You can read the str byte size and then read str bytes... */
|
||||
|
||||
if (!cmp_read_str_size(&cmp, &str_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (str_size > (sizeof(hello) - 1)) {
|
||||
error_and_exit("Packed 'hello' length too long\n");
|
||||
}
|
||||
|
||||
if (!read_bytes(hello, str_size, fh)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
/*
|
||||
* ...or you can set the maximum number of bytes to read and do it all in
|
||||
* one call
|
||||
*/
|
||||
|
||||
str_size = sizeof(message_pack);
|
||||
if (!cmp_read_str(&cmp, message_pack, &str_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
printf("Array Length: %u.\n", array_size);
|
||||
printf("[\"%s\", \"%s\"]\n", hello, message_pack);
|
||||
|
||||
fclose(fh);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
531
local_pod_repo/cmp/cmp/examples/example2.c
Normal file
531
local_pod_repo/cmp/cmp/examples/example2.c
Normal file
@@ -0,0 +1,531 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
static bool read_bytes(void *data, size_t sz, FILE *fh) {
|
||||
return fread(data, sizeof(uint8_t), sz, fh) == (sz * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
static bool file_reader(cmp_ctx_t *ctx, void *data, size_t limit) {
|
||||
return read_bytes(data, limit, (FILE *)ctx->buf);
|
||||
}
|
||||
|
||||
static bool file_skipper(cmp_ctx_t *ctx, size_t count) {
|
||||
return fseek((FILE *)ctx->buf, count, SEEK_CUR);
|
||||
}
|
||||
|
||||
static size_t file_writer(cmp_ctx_t *ctx, const void *data, size_t count) {
|
||||
return fwrite(data, sizeof(uint8_t), count, (FILE *)ctx->buf);
|
||||
}
|
||||
|
||||
static void error_and_exit(const char *msg) {
|
||||
fprintf(stderr, "%s\n\n", msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
FILE *fh = {0};
|
||||
cmp_ctx_t cmp = {0};
|
||||
uint16_t year = 1983;
|
||||
uint8_t month = 5;
|
||||
uint8_t day = 28;
|
||||
int64_t sint = 0;
|
||||
uint64_t uint = 0;
|
||||
float flt = 0.0f;
|
||||
double dbl = 0.0;
|
||||
bool boolean = false;
|
||||
uint8_t fake_bool = 0;
|
||||
uint32_t string_size = 0;
|
||||
uint32_t array_size = 0;
|
||||
uint32_t binary_size = 0;
|
||||
uint32_t map_size = 0;
|
||||
int8_t ext_type = 0;
|
||||
uint32_t ext_size = 0;
|
||||
char sbuf[12] = {0};
|
||||
|
||||
fh = fopen("cmp_data.dat", "w+b");
|
||||
|
||||
if (fh == NULL) {
|
||||
error_and_exit("Error opening data.dat");
|
||||
}
|
||||
|
||||
cmp_init(&cmp, fh, file_reader, file_skipper, file_writer);
|
||||
|
||||
/*
|
||||
* When you write an array, you first specify the number of array
|
||||
* elements, then you write that many elements.
|
||||
*/
|
||||
if (!cmp_write_array(&cmp, 9)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_sint(&cmp, -14)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_uint(&cmp, 38)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_float(&cmp, 1.8f)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_double(&cmp, 300.4)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_nil(&cmp)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_true(&cmp)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_false(&cmp)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_bool(&cmp, false)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_u8_as_bool(&cmp, 1)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
/* Array full */
|
||||
|
||||
/*
|
||||
* Maps work similar to arrays, but the length is in "pairs", so this
|
||||
* writes 2 pairs to the map. Subsequently, pairs are written in key,
|
||||
* value order.
|
||||
*/
|
||||
|
||||
if (!cmp_write_map(&cmp, 2)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
/* You can write string data all at once... */
|
||||
|
||||
if (!cmp_write_str(&cmp, "Greeting", 8)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_str(&cmp, "Hello", 5)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_str(&cmp, "Name", 4)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
/* ...or in chunks */
|
||||
|
||||
if (!cmp_write_str_marker(&cmp, 5)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (file_writer(&cmp, "Li", 2) != 2) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
if (file_writer(&cmp, "nus", 3) != 3) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
/* Map full */
|
||||
|
||||
/* Binary data functions the same as string data */
|
||||
|
||||
if (!cmp_write_bin(&cmp, "MessagePack", 11)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_write_bin_marker(&cmp, 8)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (file_writer(&cmp, "is ", 3) != 3) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
if (file_writer(&cmp, "great", 5) != 5) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
/*
|
||||
* With extended types, you can create your own custom types. Here we
|
||||
* create a simple date type.
|
||||
*/
|
||||
|
||||
/* cmp_write_ext_marker(type, size) */
|
||||
if (!cmp_write_ext_marker(&cmp, 1, 4)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
file_writer(&cmp, &year, sizeof(uint16_t));
|
||||
file_writer(&cmp, &month, sizeof(uint8_t));
|
||||
file_writer(&cmp, &day, sizeof(uint8_t));
|
||||
|
||||
/* Now we can read the data back just as easily */
|
||||
|
||||
rewind(fh);
|
||||
|
||||
if (!cmp_read_array(&cmp, &array_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (array_size != 9) {
|
||||
error_and_exit("Array size was not 9");
|
||||
}
|
||||
|
||||
if (!cmp_read_sinteger(&cmp, &sint)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (sint != -14) {
|
||||
error_and_exit("Signed int was not -14");
|
||||
}
|
||||
|
||||
if (!cmp_read_uinteger(&cmp, &uint)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (uint != 38) {
|
||||
error_and_exit("Unsigned int was not 38");
|
||||
}
|
||||
|
||||
if (!cmp_read_float(&cmp, &flt)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (flt != 1.8f) {
|
||||
error_and_exit("Float was not 1.8f");
|
||||
}
|
||||
|
||||
if (!cmp_read_double(&cmp, &dbl)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (dbl != 300.4) {
|
||||
error_and_exit("Double was not 300.f");
|
||||
}
|
||||
|
||||
if (!cmp_read_nil(&cmp)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!cmp_read_bool(&cmp, &boolean)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (boolean != true) {
|
||||
error_and_exit("First boolean was not true");
|
||||
}
|
||||
|
||||
if (!cmp_read_bool(&cmp, &boolean)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (boolean != false) {
|
||||
error_and_exit("Second boolean was not false");
|
||||
}
|
||||
|
||||
if (!cmp_read_bool(&cmp, &boolean)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (boolean != false) {
|
||||
error_and_exit("Third boolean was not false");
|
||||
}
|
||||
|
||||
if (!cmp_read_bool_as_u8(&cmp, &fake_bool)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (fake_bool != 1) {
|
||||
fprintf(stderr, "%u.\n", fake_bool);
|
||||
error_and_exit("Third boolean (u8) was not 1");
|
||||
}
|
||||
|
||||
if (!cmp_read_map(&cmp, &map_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (map_size != 2) {
|
||||
error_and_exit("Map size was not 2");
|
||||
}
|
||||
|
||||
/*
|
||||
* String reading here. Note that normally strings are encoded using
|
||||
* UTF-8. I have cleverly restricted this example to ASCII, which overlaps
|
||||
* UTF-8 encoding, but this must not be assumed in real-world code.
|
||||
*
|
||||
* You can read strings in two ways. Either you can read the string's size
|
||||
* in bytes and then read the bytes manually...
|
||||
*/
|
||||
|
||||
if (!cmp_read_str_size(&cmp, &string_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (string_size != 8) {
|
||||
error_and_exit("Greeting string key size was not 8");
|
||||
}
|
||||
|
||||
if (!read_bytes(sbuf, 8, fh)) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
sbuf[string_size] = 0;
|
||||
|
||||
if (strncmp(sbuf, "Greeting", 8) != 0) {
|
||||
error_and_exit("Greeting string key name was not 'Greeting'");
|
||||
}
|
||||
|
||||
/*
|
||||
* ...or you can set the maximum number of bytes to read and do it all in
|
||||
* one call. cmp_read_str will write no more than "size" bytes, including
|
||||
* the terminating NULL, to the passed buffer. If the string's size
|
||||
* exceeds the passed buffer size, the "size" input is set to the number of
|
||||
* bytes necessary, not including the terminating NULL. Otherwise, the
|
||||
* "size" input is set to the number of bytes written, not including the
|
||||
* terminating NULL.
|
||||
*/
|
||||
|
||||
string_size = sizeof(sbuf);
|
||||
if (!cmp_read_str(&cmp, sbuf, &string_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (strncmp(sbuf, "Hello", 5) != 0) {
|
||||
error_and_exit("Greeting string value was not 'Hello'");
|
||||
}
|
||||
|
||||
string_size = sizeof(sbuf);
|
||||
if (!cmp_read_str(&cmp, sbuf, &string_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (strncmp(sbuf, "Name", 4) != 0) {
|
||||
error_and_exit("Name key name was not 'Name'");
|
||||
}
|
||||
|
||||
string_size = sizeof(sbuf);
|
||||
if (!cmp_read_str(&cmp, sbuf, &string_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (strncmp(sbuf, "Linus", 5) != 0) {
|
||||
error_and_exit("Name key value was not 'Linus'");
|
||||
}
|
||||
|
||||
memset(sbuf, 0, sizeof(sbuf));
|
||||
binary_size = sizeof(sbuf);
|
||||
if (!cmp_read_bin(&cmp, sbuf, &binary_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (memcmp(sbuf, "MessagePack", 11) != 0) {
|
||||
error_and_exit("1st binary value was not 'MessagePack'");
|
||||
}
|
||||
|
||||
memset(sbuf, 0, sizeof(sbuf));
|
||||
binary_size = sizeof(sbuf);
|
||||
if (!cmp_read_bin(&cmp, sbuf, &binary_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (memcmp(sbuf, "is great", 8) != 0) {
|
||||
error_and_exit("2nd binary value was not 'is great'");
|
||||
}
|
||||
|
||||
if (!cmp_read_ext_marker(&cmp, &ext_type, &ext_size)) {
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
if (!read_bytes(&year, sizeof(uint16_t), fh)) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
if (!read_bytes(&month, sizeof(uint8_t), fh)) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
if (!read_bytes(&day, sizeof(uint8_t), fh)) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
if (year != 1983) {
|
||||
error_and_exit("Year was not 1983");
|
||||
}
|
||||
|
||||
if (month != 5) {
|
||||
error_and_exit("Month was not 5");
|
||||
}
|
||||
|
||||
if (day != 28) {
|
||||
error_and_exit("Day was not 28");
|
||||
}
|
||||
|
||||
rewind(fh);
|
||||
|
||||
/* Alternately, you can read objects until the stream is empty */
|
||||
while (1) {
|
||||
cmp_object_t obj;
|
||||
|
||||
if (!cmp_read_object(&cmp, &obj)) {
|
||||
if (feof(fh)) {
|
||||
break;
|
||||
}
|
||||
|
||||
error_and_exit(cmp_strerror(&cmp));
|
||||
}
|
||||
|
||||
switch (obj.type) {
|
||||
case CMP_TYPE_POSITIVE_FIXNUM:
|
||||
case CMP_TYPE_UINT8:
|
||||
printf("Unsigned Integer: %u\n", obj.as.u8);
|
||||
break;
|
||||
case CMP_TYPE_FIXMAP:
|
||||
case CMP_TYPE_MAP16:
|
||||
case CMP_TYPE_MAP32:
|
||||
printf("Map: %u\n", obj.as.map_size);
|
||||
break;
|
||||
case CMP_TYPE_FIXARRAY:
|
||||
case CMP_TYPE_ARRAY16:
|
||||
case CMP_TYPE_ARRAY32:
|
||||
printf("Array: %u\n", obj.as.array_size);
|
||||
break;
|
||||
case CMP_TYPE_FIXSTR:
|
||||
case CMP_TYPE_STR8:
|
||||
case CMP_TYPE_STR16:
|
||||
case CMP_TYPE_STR32:
|
||||
if (!read_bytes(sbuf, obj.as.str_size, fh)) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
sbuf[obj.as.str_size] = 0;
|
||||
printf("String: %s\n", sbuf);
|
||||
break;
|
||||
case CMP_TYPE_BIN8:
|
||||
case CMP_TYPE_BIN16:
|
||||
case CMP_TYPE_BIN32:
|
||||
memset(sbuf, 0, sizeof(sbuf));
|
||||
if (!read_bytes(sbuf, obj.as.bin_size, fh)) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
printf("Binary: %s\n", sbuf);
|
||||
break;
|
||||
case CMP_TYPE_NIL:
|
||||
printf("NULL\n");
|
||||
break;
|
||||
case CMP_TYPE_BOOLEAN:
|
||||
if (obj.as.boolean) {
|
||||
printf("Boolean: true\n");
|
||||
}
|
||||
else {
|
||||
printf("Boolean: false\n");
|
||||
}
|
||||
break;
|
||||
case CMP_TYPE_EXT8:
|
||||
case CMP_TYPE_EXT16:
|
||||
case CMP_TYPE_EXT32:
|
||||
case CMP_TYPE_FIXEXT1:
|
||||
case CMP_TYPE_FIXEXT2:
|
||||
case CMP_TYPE_FIXEXT4:
|
||||
case CMP_TYPE_FIXEXT8:
|
||||
case CMP_TYPE_FIXEXT16:
|
||||
if (obj.as.ext.type == 1) { /* Date object */
|
||||
if (!read_bytes(&year, sizeof(uint16_t), fh)) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
if (!read_bytes(&month, sizeof(uint8_t), fh)) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
if (!read_bytes(&day, sizeof(uint8_t), fh)) {
|
||||
error_and_exit(strerror(errno));
|
||||
}
|
||||
|
||||
printf("Date: %u/%u/%u\n", year, month, day);
|
||||
}
|
||||
else {
|
||||
printf("Extended type {%d, %u}: ",
|
||||
obj.as.ext.type, obj.as.ext.size
|
||||
);
|
||||
while (obj.as.ext.size--) {
|
||||
read_bytes(sbuf, sizeof(uint8_t), fh);
|
||||
printf("%02x ", sbuf[0]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
break;
|
||||
case CMP_TYPE_FLOAT:
|
||||
printf("Float: %f\n", obj.as.flt);
|
||||
break;
|
||||
case CMP_TYPE_DOUBLE:
|
||||
printf("Double: %f\n", obj.as.dbl);
|
||||
break;
|
||||
case CMP_TYPE_UINT16:
|
||||
printf("Unsigned Integer: %u\n", obj.as.u16);
|
||||
break;
|
||||
case CMP_TYPE_UINT32:
|
||||
printf("Unsigned Integer: %u\n", obj.as.u32);
|
||||
break;
|
||||
case CMP_TYPE_UINT64:
|
||||
printf("Unsigned Integer: %" PRIu64 "\n", obj.as.u64);
|
||||
break;
|
||||
case CMP_TYPE_NEGATIVE_FIXNUM:
|
||||
case CMP_TYPE_SINT8:
|
||||
printf("Signed Integer: %d\n", obj.as.s8);
|
||||
break;
|
||||
case CMP_TYPE_SINT16:
|
||||
printf("Signed Integer: %d\n", obj.as.s16);
|
||||
break;
|
||||
case CMP_TYPE_SINT32:
|
||||
printf("Signed Integer: %d\n", obj.as.s32);
|
||||
break;
|
||||
case CMP_TYPE_SINT64:
|
||||
printf("Signed Integer: %" PRId64 "\n", obj.as.s64);
|
||||
break;
|
||||
default:
|
||||
printf("Unrecognized object type %u\n", obj.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fh);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
569
local_pod_repo/cmp/cmp/test/buf.c
Normal file
569
local_pod_repo/cmp/cmp/test/buf.c
Normal file
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "buf.h"
|
||||
|
||||
|
||||
static void check_cursor(buf_t *buf) {
|
||||
if (buf->cursor > buf->size)
|
||||
buf->size = buf->cursor;
|
||||
}
|
||||
|
||||
buf_t* M_BufferNew(void) {
|
||||
buf_t *buf = calloc(1, sizeof(buf_t));
|
||||
|
||||
if (buf == NULL)
|
||||
error_and_exit("M_BufferNew: Calloc returned NULL.");
|
||||
|
||||
M_BufferInit(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
buf_t* M_BufferNewWithCapacity(size_t capacity) {
|
||||
buf_t *buf = calloc(1, sizeof(buf_t));
|
||||
|
||||
if (buf == NULL)
|
||||
error_and_exit("M_BufferNew: calloc returned NULL");
|
||||
|
||||
M_BufferInitWithCapacity(buf, capacity);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void M_BufferInit(buf_t *buf) {
|
||||
buf->size = 0;
|
||||
buf->capacity = 0;
|
||||
buf->cursor = 0;
|
||||
buf->data = NULL;
|
||||
}
|
||||
|
||||
void M_BufferInitWithCapacity(buf_t *buf, size_t capacity) {
|
||||
M_BufferInit(buf);
|
||||
M_BufferEnsureTotalCapacity(buf, capacity);
|
||||
}
|
||||
|
||||
size_t M_BufferGetCapacity(const buf_t *buf) {
|
||||
return buf->capacity;
|
||||
}
|
||||
|
||||
size_t M_BufferGetSize(const buf_t *buf) {
|
||||
return buf->size;
|
||||
}
|
||||
|
||||
size_t M_BufferGetCursor(const buf_t *buf) {
|
||||
return buf->cursor;
|
||||
}
|
||||
|
||||
char* M_BufferGetData(const buf_t *buf) {
|
||||
return buf->data;
|
||||
}
|
||||
|
||||
char* M_BufferGetDataAtCursor(const buf_t *buf) {
|
||||
return buf->data + buf->cursor;
|
||||
}
|
||||
|
||||
void M_BufferEnsureCapacity(buf_t *buf, size_t capacity) {
|
||||
size_t needed_capacity = buf->cursor + capacity;
|
||||
|
||||
if (buf->capacity < needed_capacity) {
|
||||
buf->data = realloc(buf->data, needed_capacity * sizeof(uint8_t));
|
||||
|
||||
if (buf->data == NULL) {
|
||||
error_and_exit(
|
||||
"M_BufferEnsureCapacity: Reallocating buffer data failed"
|
||||
);
|
||||
}
|
||||
|
||||
memset(buf->data + buf->capacity, 0, needed_capacity - buf->capacity);
|
||||
buf->capacity = needed_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
void M_BufferEnsureTotalCapacity(buf_t *buf, size_t capacity) {
|
||||
if (buf->capacity < capacity) {
|
||||
size_t old_capacity = buf->capacity;
|
||||
|
||||
buf->capacity = capacity;
|
||||
buf->data = realloc(buf->data, buf->capacity * sizeof(uint8_t));
|
||||
|
||||
if (buf->data == NULL)
|
||||
error_and_exit("M_BufferEnsureCapacity: Allocating buffer data failed");
|
||||
|
||||
memset(buf->data + old_capacity, 0, buf->capacity - old_capacity);
|
||||
}
|
||||
}
|
||||
|
||||
void M_BufferCopy(buf_t *dst, const buf_t *src) {
|
||||
M_BufferSetData(dst, M_BufferGetData(src), M_BufferGetSize(src));
|
||||
}
|
||||
|
||||
void M_BufferCursorCopy(buf_t *dst, const buf_t *src) {
|
||||
M_BufferWrite(
|
||||
dst,
|
||||
M_BufferGetDataAtCursor(src),
|
||||
M_BufferGetSize(src) - (M_BufferGetCursor(src) - 1)
|
||||
);
|
||||
}
|
||||
|
||||
bool M_BufferMove(buf_t *buf, size_t dpos, size_t spos, size_t count) {
|
||||
if ((spos + count) > M_BufferGetSize(buf))
|
||||
return false;
|
||||
|
||||
M_BufferEnsureTotalCapacity(buf, dpos + count);
|
||||
|
||||
memmove(M_BufferGetData(buf) + dpos, M_BufferGetData(buf) + spos, count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void M_BufferSetData(buf_t *buf, const void *data, size_t size) {
|
||||
M_BufferClear(buf);
|
||||
M_BufferEnsureTotalCapacity(buf, size);
|
||||
M_BufferWrite(buf, data, size);
|
||||
}
|
||||
|
||||
void M_BufferSetString(buf_t *buf, const char *data, size_t length) {
|
||||
M_BufferClear(buf);
|
||||
M_BufferWriteString(buf, data, length);
|
||||
}
|
||||
|
||||
bool M_BufferSetFile(buf_t *buf, const char *filename) {
|
||||
FILE *fp;
|
||||
size_t length;
|
||||
bool out = false;
|
||||
|
||||
if ((fp = fopen(filename, "rb")) == NULL)
|
||||
return false;
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
length = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
M_BufferClear(buf);
|
||||
M_BufferEnsureTotalCapacity(buf, length);
|
||||
|
||||
if (fread(buf->data, sizeof(uint8_t), length, fp) == length) {
|
||||
buf->cursor = length;
|
||||
buf->size = length;
|
||||
out = true;
|
||||
}
|
||||
else {
|
||||
M_BufferClear(buf);
|
||||
out = false;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return out;
|
||||
}
|
||||
|
||||
bool M_BufferSeek(buf_t *buf, size_t pos) {
|
||||
if (pos > buf->size)
|
||||
return false;
|
||||
|
||||
buf->cursor = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool M_BufferSeekBackward(buf_t *buf, size_t count) {
|
||||
if (count > buf->cursor)
|
||||
return false;
|
||||
|
||||
buf->cursor -= count;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool M_BufferSeekForward(buf_t *buf, size_t count) {
|
||||
if (buf->cursor + count > buf->size)
|
||||
return false;
|
||||
|
||||
buf->cursor += count;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t M_BufferPeek(const buf_t *buf) {
|
||||
return *(buf->data + buf->cursor);
|
||||
}
|
||||
|
||||
void M_BufferWrite(buf_t *buf, const void *data, size_t size) {
|
||||
M_BufferEnsureCapacity(buf, size);
|
||||
memcpy(buf->data + buf->cursor, data, size);
|
||||
buf->cursor += size;
|
||||
|
||||
check_cursor(buf);
|
||||
}
|
||||
|
||||
void M_BufferWriteBool(buf_t *buf, bool b) {
|
||||
M_BufferWriteBools(buf, &b, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteBools(buf_t *buf, const bool *bools, size_t count) {
|
||||
M_BufferEnsureCapacity(buf, count * sizeof(bool));
|
||||
M_BufferWriteChars(buf, (char *)bools, count * sizeof(bool));
|
||||
}
|
||||
|
||||
void M_BufferWriteChar(buf_t *buf, char c) {
|
||||
M_BufferWriteChars(buf, &c, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteChars(buf_t *buf, const char *chars, size_t count) {
|
||||
M_BufferWrite(buf, chars, count * sizeof(char));
|
||||
}
|
||||
|
||||
void M_BufferWriteUChar(buf_t *buf, unsigned char c) {
|
||||
M_BufferWriteUChars(buf, &c, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteUChars(buf_t *buf, const unsigned char *uchars, size_t count) {
|
||||
M_BufferWrite(buf, uchars, count * sizeof(unsigned char));
|
||||
}
|
||||
|
||||
void M_BufferWriteShort(buf_t *buf, short s) {
|
||||
M_BufferWriteShorts(buf, &s, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteShorts(buf_t *buf, const short *shorts, size_t count) {
|
||||
M_BufferEnsureCapacity(buf, count * sizeof(short));
|
||||
M_BufferWriteChars(buf, (char *)shorts, count * sizeof(short));
|
||||
}
|
||||
|
||||
void M_BufferWriteUShort(buf_t *buf, unsigned short s) {
|
||||
M_BufferWriteUShorts(buf, &s, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteUShorts(buf_t *buf, const unsigned short *ushorts,
|
||||
size_t count) {
|
||||
M_BufferEnsureCapacity(buf, count * sizeof(unsigned short));
|
||||
M_BufferWriteChars(buf, (char *)ushorts, count * sizeof(unsigned short));
|
||||
}
|
||||
|
||||
void M_BufferWriteInt(buf_t *buf, int i) {
|
||||
M_BufferWriteInts(buf, &i, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteInts(buf_t *buf, const int *ints, size_t count) {
|
||||
M_BufferEnsureCapacity(buf, count * sizeof(int));
|
||||
M_BufferWriteChars(buf, (char *)ints, count * sizeof(int));
|
||||
}
|
||||
|
||||
void M_BufferWriteUInt(buf_t *buf, unsigned int s) {
|
||||
M_BufferWriteUInts(buf, &s, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteUInts(buf_t *buf, const unsigned int *uints, size_t count) {
|
||||
M_BufferEnsureCapacity(buf, count * sizeof(unsigned int));
|
||||
M_BufferWriteChars(buf, (char *)uints, count * sizeof(unsigned int));
|
||||
}
|
||||
|
||||
void M_BufferWriteLong(buf_t *buf, int64_t l) {
|
||||
M_BufferWriteLongs(buf, &l, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteLongs(buf_t *buf, const int64_t *longs, size_t count) {
|
||||
M_BufferEnsureCapacity(buf, count * sizeof(int64_t));
|
||||
M_BufferWriteChars(buf, (char *)longs, count * sizeof(int64_t));
|
||||
}
|
||||
|
||||
void M_BufferWriteULong(buf_t *buf, uint64_t l) {
|
||||
M_BufferWriteULongs(buf, &l, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteULongs(buf_t *buf, const uint64_t *ulongs, size_t count) {
|
||||
M_BufferEnsureCapacity(buf, count * sizeof(int64_t));
|
||||
M_BufferWriteChars(buf, (char *)ulongs, count * sizeof(uint64_t));
|
||||
}
|
||||
|
||||
#ifndef CMP_NO_FLOAT
|
||||
void M_BufferWriteFloat(buf_t *buf, float f) {
|
||||
M_BufferWriteFloats(buf, &f, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteFloats(buf_t *buf, const float *floats, size_t count) {
|
||||
M_BufferEnsureCapacity(buf, count * sizeof(float));
|
||||
M_BufferWriteChars(buf, (char *)floats, count * sizeof(floats));
|
||||
}
|
||||
|
||||
void M_BufferWriteDouble(buf_t *buf, double d) {
|
||||
M_BufferWriteDoubles(buf, &d, 1);
|
||||
}
|
||||
|
||||
void M_BufferWriteDoubles(buf_t *buf, const double *doubles, size_t count) {
|
||||
M_BufferEnsureCapacity(buf, count * sizeof(double));
|
||||
M_BufferWriteChars(buf, (char *)doubles, count * sizeof(doubles));
|
||||
}
|
||||
#endif
|
||||
|
||||
void M_BufferWriteString(buf_t *buf, const char *string, size_t length) {
|
||||
M_BufferEnsureCapacity(buf, length + 1);
|
||||
strncpy(buf->data + buf->cursor, string, length + 1);
|
||||
buf->cursor += (length + 1);
|
||||
|
||||
check_cursor(buf);
|
||||
}
|
||||
|
||||
void M_BufferWriteZeros(buf_t *buf, size_t count) {
|
||||
M_BufferEnsureCapacity(buf, count);
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
buf->data[buf->cursor++] = 0;
|
||||
|
||||
check_cursor(buf);
|
||||
}
|
||||
|
||||
bool M_BufferEqualsString(const buf_t *buf, const char *s) {
|
||||
if (strncmp(buf->data + buf->cursor, s, buf->size - buf->cursor) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool M_BufferEqualsData(const buf_t *buf, const void *d, size_t size) {
|
||||
if (buf->cursor + size > buf->size)
|
||||
return false;
|
||||
|
||||
if (memcmp(buf->data + buf->cursor, d, size) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool M_BufferRead(buf_t *buf, void *data, size_t size) {
|
||||
if (buf->cursor + size > buf->size)
|
||||
return false;
|
||||
|
||||
if (size == 1)
|
||||
*((char *)data) = *(buf->data + buf->cursor);
|
||||
else
|
||||
memcpy(data, buf->data + buf->cursor, size);
|
||||
|
||||
buf->cursor += size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool M_BufferReadBool(buf_t *buf, bool *b) {
|
||||
return M_BufferReadBools(buf, b, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadBools(buf_t *buf, bool *b, size_t count) {
|
||||
return M_BufferRead(buf, b, count * sizeof(bool));
|
||||
}
|
||||
|
||||
bool M_BufferReadChar(buf_t *buf, char *c) {
|
||||
return M_BufferReadChars(buf, c, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadChars(buf_t *buf, char *c, size_t count) {
|
||||
return M_BufferRead(buf, c, count * sizeof(char));
|
||||
}
|
||||
|
||||
bool M_BufferReadUChar(buf_t *buf, unsigned char *c) {
|
||||
return M_BufferReadUChars(buf, c, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadUChars(buf_t *buf, unsigned char *c, size_t count) {
|
||||
return M_BufferRead(buf, c, count * sizeof(unsigned char));
|
||||
}
|
||||
|
||||
bool M_BufferReadShort(buf_t *buf, short *s) {
|
||||
return M_BufferReadShorts(buf, s, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadShorts(buf_t *buf, short *s, size_t count) {
|
||||
return M_BufferRead(buf, s, count * sizeof(short));
|
||||
}
|
||||
|
||||
bool M_BufferReadUShort(buf_t *buf, unsigned short *s) {
|
||||
return M_BufferReadUShorts(buf, s, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadUShorts(buf_t *buf, unsigned short *s, size_t count) {
|
||||
return M_BufferRead(buf, s, count * sizeof(unsigned short));
|
||||
}
|
||||
|
||||
bool M_BufferReadInt(buf_t *buf, int *i) {
|
||||
return M_BufferReadInts(buf, i, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadInts(buf_t *buf, int *i, size_t count) {
|
||||
return M_BufferRead(buf, i, count * sizeof(int));
|
||||
}
|
||||
|
||||
bool M_BufferReadUInt(buf_t *buf, unsigned int *i) {
|
||||
return M_BufferReadUInts(buf, i, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadUInts(buf_t *buf, unsigned int *i, size_t count) {
|
||||
return M_BufferRead(buf, i, count * sizeof(unsigned int));
|
||||
}
|
||||
|
||||
bool M_BufferReadLong(buf_t *buf, int64_t *l) {
|
||||
return M_BufferReadLongs(buf, l, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadLongs(buf_t *buf, int64_t *l, size_t count) {
|
||||
return M_BufferRead(buf, l, count * sizeof(int64_t));
|
||||
}
|
||||
|
||||
bool M_BufferReadULong(buf_t *buf, uint64_t *l) {
|
||||
return M_BufferReadULongs(buf, l, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadULongs(buf_t *buf, uint64_t *l, size_t count) {
|
||||
return M_BufferRead(buf, l, count * sizeof(uint64_t));
|
||||
}
|
||||
|
||||
#ifndef CMP_NO_FLOAT
|
||||
bool M_BufferReadFloat(buf_t *buf, float *f) {
|
||||
return M_BufferReadFloats(buf, f, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadFloats(buf_t *buf, float *f, size_t count) {
|
||||
return M_BufferRead(buf, f, count * sizeof(float));
|
||||
}
|
||||
|
||||
bool M_BufferReadDouble(buf_t *buf, double *d) {
|
||||
return M_BufferReadDoubles(buf, d, 1);
|
||||
}
|
||||
|
||||
bool M_BufferReadDoubles(buf_t *buf, double *d, size_t count) {
|
||||
return M_BufferRead(buf, d, count * sizeof(double));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool M_BufferReadString(buf_t *buf, char *s, size_t length) {
|
||||
return M_BufferRead(buf, s, length);
|
||||
}
|
||||
|
||||
bool M_BufferReadStringDup(const buf_t *buf, char **s) {
|
||||
char *d = buf->data + buf->cursor;
|
||||
size_t length = strlen(d);
|
||||
|
||||
if (buf->cursor + length > buf->size)
|
||||
return false;
|
||||
|
||||
(*s) = strdup(buf->data + buf->cursor);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool M_BufferCopyString(buf_t *dst, const buf_t *src) {
|
||||
char *s = src->data + src->cursor;
|
||||
size_t length = strlen(s);
|
||||
|
||||
if (src->cursor + length >= src->size)
|
||||
return false;
|
||||
|
||||
M_BufferWriteString(dst, s, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
void M_BufferCompact(buf_t *buf) {
|
||||
if (buf->size < buf->capacity) {
|
||||
char *new_buf = calloc(buf->size, sizeof(uint8_t));
|
||||
|
||||
if (buf->data == NULL)
|
||||
error_and_exit("M_BufferCompact: Allocating new buffer data failed");
|
||||
|
||||
memcpy(new_buf, buf->data, buf->size);
|
||||
free(buf->data);
|
||||
buf->data = new_buf;
|
||||
buf->capacity = buf->size;
|
||||
if (buf->cursor > buf->size)
|
||||
buf->cursor = buf->size;
|
||||
}
|
||||
}
|
||||
|
||||
void M_BufferTruncate(buf_t *buf, size_t new_size) {
|
||||
size_t old_size = buf->size;
|
||||
|
||||
if (new_size >= buf->size)
|
||||
errorf_and_exit("M_BufferTruncate: %zu >= %zu.", new_size, buf->size);
|
||||
|
||||
memset(buf->data + new_size, 0, old_size - new_size);
|
||||
buf->size = new_size;
|
||||
|
||||
if (buf->cursor >= buf->size)
|
||||
buf->cursor = buf->size - 1;
|
||||
}
|
||||
|
||||
void M_BufferZero(const buf_t *buf) {
|
||||
memset(buf->data, 0, buf->capacity);
|
||||
}
|
||||
|
||||
void M_BufferClear(buf_t *buf) {
|
||||
buf->size = 0;
|
||||
buf->cursor = 0;
|
||||
M_BufferZero(buf);
|
||||
}
|
||||
|
||||
void M_BufferFree(buf_t *buf) {
|
||||
free(buf->data);
|
||||
memset(buf, 0, sizeof(buf_t));
|
||||
buf->data = NULL;
|
||||
}
|
||||
|
||||
void M_BufferPrint(const buf_t *buf) {
|
||||
printf("Buffer capacity, size and cursor: [%zu, %zu, %zu].\n",
|
||||
buf->capacity,
|
||||
buf->size,
|
||||
buf->cursor
|
||||
);
|
||||
|
||||
for (size_t i = 0; i < MIN(64, buf->size); i++) {
|
||||
printf("%02X ", (unsigned char)buf->data[i]);
|
||||
|
||||
if ((i > 0) && (((i + 1) % 25) == 0))
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void M_BufferPrintAll(const buf_t *buf) {
|
||||
printf("Buffer capacity, size and cursor: [%zu, %zu, %zu].\n",
|
||||
buf->capacity,
|
||||
buf->size,
|
||||
buf->cursor
|
||||
);
|
||||
|
||||
for (size_t i = 0; i < buf->size; i++) {
|
||||
printf("%02X ", (unsigned char)buf->data[i]);
|
||||
|
||||
if ((i > 0) && (((i + 1) % 25) == 0))
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* vi: set et ts=2 sw=2: */
|
||||
|
||||
138
local_pod_repo/cmp/cmp/test/buf.h
Normal file
138
local_pod_repo/cmp/cmp/test/buf.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef M_BUF_H__
|
||||
#define M_BUF_H__
|
||||
|
||||
typedef struct buf_s {
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
size_t cursor;
|
||||
char *data;
|
||||
} buf_t;
|
||||
|
||||
buf_t* M_BufferNew(void);
|
||||
buf_t* M_BufferNewWithCapacity(size_t capacity);
|
||||
void M_BufferInit(buf_t *buf);
|
||||
void M_BufferInitWithCapacity(buf_t *buf, size_t capacity);
|
||||
|
||||
size_t M_BufferGetCapacity(const buf_t *buf);
|
||||
size_t M_BufferGetSize(const buf_t *buf);
|
||||
size_t M_BufferGetCursor(const buf_t *buf);
|
||||
char* M_BufferGetData(const buf_t *buf);
|
||||
char* M_BufferGetDataAtCursor(const buf_t *buf);
|
||||
|
||||
void M_BufferEnsureCapacity(buf_t *buf, size_t capacity);
|
||||
void M_BufferEnsureTotalCapacity(buf_t *buf, size_t capacity);
|
||||
|
||||
void M_BufferCopy(buf_t *dst, const buf_t *src);
|
||||
void M_BufferCursorCopy(buf_t *dst, const buf_t *src);
|
||||
bool M_BufferMove(buf_t *buf, size_t dpos, size_t spos, size_t count);
|
||||
|
||||
void M_BufferSetData(buf_t *buf, const void *data, size_t size);
|
||||
void M_BufferSetString(buf_t *buf, const char *data, size_t length);
|
||||
bool M_BufferSetFile(buf_t *buf, const char *filename);
|
||||
|
||||
bool M_BufferSeek(buf_t *buf, size_t pos);
|
||||
bool M_BufferSeekBackward(buf_t *buf, size_t count);
|
||||
bool M_BufferSeekForward(buf_t *buf, size_t count);
|
||||
|
||||
uint8_t M_BufferPeek(const buf_t *buf);
|
||||
|
||||
void M_BufferWrite(buf_t *buf, const void *data, size_t size);
|
||||
void M_BufferWriteBool(buf_t *buf, bool b);
|
||||
void M_BufferWriteBools(buf_t *buf, const bool *bools, size_t count);
|
||||
void M_BufferWriteChar(buf_t *buf, char c);
|
||||
void M_BufferWriteChars(buf_t *buf, const char *chars, size_t count);
|
||||
void M_BufferWriteUChar(buf_t *buf, unsigned char c);
|
||||
void M_BufferWriteUChars(buf_t *buf, const unsigned char *uchars,
|
||||
size_t count);
|
||||
void M_BufferWriteShort(buf_t *buf, short s);
|
||||
void M_BufferWriteShorts(buf_t *buf, const short *shorts, size_t count);
|
||||
void M_BufferWriteUShort(buf_t *buf, unsigned short s);
|
||||
void M_BufferWriteUShorts(buf_t *buf, const unsigned short *ushorts,
|
||||
size_t count);
|
||||
void M_BufferWriteInt(buf_t *buf, int i);
|
||||
void M_BufferWriteInts(buf_t *buf, const int *ints, size_t count);
|
||||
void M_BufferWriteUInt(buf_t *buf, unsigned int i);
|
||||
void M_BufferWriteUInts(buf_t *buf, const unsigned int *ints,
|
||||
size_t count);
|
||||
void M_BufferWriteLong(buf_t *buf, int64_t l);
|
||||
void M_BufferWriteLongs(buf_t *buf, const int64_t *longs, size_t count);
|
||||
void M_BufferWriteULong(buf_t *buf, uint64_t l);
|
||||
void M_BufferWriteULongs(buf_t *buf, const uint64_t *longs, size_t count);
|
||||
#ifndef CMP_NO_FLOAT
|
||||
void M_BufferWriteFloat(buf_t *buf, float f);
|
||||
void M_BufferWriteFloats(buf_t *buf, const float *floats, size_t count);
|
||||
void M_BufferWriteDouble(buf_t *buf, double d);
|
||||
void M_BufferWriteDoubles(buf_t *buf, const double *doubles, size_t count);
|
||||
#endif
|
||||
void M_BufferWriteString(buf_t *buf, const char *string, size_t length);
|
||||
void M_BufferWriteZeros(buf_t *buf, size_t count);
|
||||
|
||||
bool M_BufferEqualsString(const buf_t *buf, const char *s);
|
||||
bool M_BufferEqualsData(const buf_t *buf, const void *d, size_t size);
|
||||
|
||||
bool M_BufferRead(buf_t *buf, void *data, size_t size);
|
||||
bool M_BufferReadBool(buf_t *buf, bool *b);
|
||||
bool M_BufferReadBools(buf_t *buf, bool *b, size_t count);
|
||||
bool M_BufferReadChar(buf_t *buf, char *c);
|
||||
bool M_BufferReadChars(buf_t *buf, char *c, size_t count);
|
||||
bool M_BufferReadUChar(buf_t *buf, unsigned char *c);
|
||||
bool M_BufferReadUChars(buf_t *buf, unsigned char *c, size_t count);
|
||||
bool M_BufferReadShort(buf_t *buf, short *s);
|
||||
bool M_BufferReadShorts(buf_t *buf, short *shorts, size_t count);
|
||||
bool M_BufferReadUShort(buf_t *buf, unsigned short *s);
|
||||
bool M_BufferReadUShorts(buf_t *buf, unsigned short *s, size_t count);
|
||||
bool M_BufferReadInt(buf_t *buf, int *i);
|
||||
bool M_BufferReadInts(buf_t *buf, int *i, size_t count);
|
||||
bool M_BufferReadUInt(buf_t *buf, unsigned int *i);
|
||||
bool M_BufferReadUInts(buf_t *buf, unsigned int *i, size_t count);
|
||||
bool M_BufferReadLong(buf_t *buf, int64_t *l);
|
||||
bool M_BufferReadLongs(buf_t *buf, int64_t *l, size_t count);
|
||||
bool M_BufferReadULong(buf_t *buf, uint64_t *l);
|
||||
bool M_BufferReadULongs(buf_t *buf, uint64_t *l, size_t count);
|
||||
#ifndef CMP_NO_FLOAT
|
||||
bool M_BufferReadFloat(buf_t *buf, float *f);
|
||||
bool M_BufferReadFloats(buf_t *buf, float *f, size_t count);
|
||||
bool M_BufferReadDouble(buf_t *buf, double *d);
|
||||
bool M_BufferReadDoubles(buf_t *buf, double *d, size_t count);
|
||||
#endif
|
||||
bool M_BufferReadString(buf_t *buf, char *s, size_t length);
|
||||
bool M_BufferReadStringDup(const buf_t *buf, char **s);
|
||||
bool M_BufferCopyString(buf_t *dst, const buf_t *src);
|
||||
|
||||
void M_BufferCompact(buf_t *buf);
|
||||
void M_BufferTruncate(buf_t *buf, size_t new_size);
|
||||
void M_BufferZero(const buf_t *buf);
|
||||
void M_BufferClear(buf_t *buf);
|
||||
void M_BufferFree(buf_t *buf);
|
||||
|
||||
void M_BufferPrint(const buf_t *buf);
|
||||
void M_BufferPrintAll(const buf_t *buf);
|
||||
|
||||
#endif
|
||||
|
||||
/* vi: set et ts=2 sw=2: */
|
||||
|
||||
BIN
local_pod_repo/cmp/cmp/test/cases.mpac
Normal file
BIN
local_pod_repo/cmp/cmp/test/cases.mpac
Normal file
Binary file not shown.
55
local_pod_repo/cmp/cmp/test/profile.c
Normal file
55
local_pod_repo/cmp/cmp/test/profile.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
int main(void) {
|
||||
test_msgpack(NULL);
|
||||
test_fixedint(NULL);
|
||||
test_numbers(NULL);
|
||||
test_nil(NULL);
|
||||
test_boolean(NULL);
|
||||
test_bin(NULL);
|
||||
test_string(NULL);
|
||||
test_array(NULL);
|
||||
test_map(NULL);
|
||||
test_ext(NULL);
|
||||
test_obj(NULL);
|
||||
|
||||
#ifndef CMP_NO_FLOAT
|
||||
test_float_flip(NULL);
|
||||
#endif
|
||||
|
||||
test_skipping(NULL);
|
||||
test_deprecated_limited_skipping(NULL);
|
||||
test_errors(NULL);
|
||||
test_version(NULL);
|
||||
test_conversions(NULL);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* vi: set et ts=2 sw=2: */
|
||||
67
local_pod_repo/cmp/cmp/test/test.c
Normal file
67
local_pod_repo/cmp/cmp/test/test.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
int main(void) {
|
||||
/* Use the old CMocka API because Travis' latest Ubuntu is Trusty */
|
||||
const UnitTest tests[17] = {
|
||||
unit_test(test_msgpack),
|
||||
unit_test(test_fixedint),
|
||||
unit_test(test_numbers),
|
||||
unit_test(test_nil),
|
||||
unit_test(test_boolean),
|
||||
unit_test(test_bin),
|
||||
unit_test(test_string),
|
||||
unit_test(test_array),
|
||||
unit_test(test_map),
|
||||
unit_test(test_ext),
|
||||
unit_test(test_obj),
|
||||
|
||||
#ifndef CMP_NO_FLOAT
|
||||
unit_test(test_float_flip),
|
||||
#endif
|
||||
|
||||
unit_test(test_skipping),
|
||||
unit_test(test_deprecated_limited_skipping),
|
||||
unit_test(test_errors),
|
||||
unit_test(test_version),
|
||||
unit_test(test_conversions),
|
||||
};
|
||||
|
||||
if (run_tests(tests)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* vi: set et ts=2 sw=2: */
|
||||
5951
local_pod_repo/cmp/cmp/test/tests.c
Normal file
5951
local_pod_repo/cmp/cmp/test/tests.c
Normal file
File diff suppressed because it is too large
Load Diff
45
local_pod_repo/cmp/cmp/test/tests.h
Normal file
45
local_pod_repo/cmp/cmp/test/tests.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
void test_msgpack(void **state);
|
||||
void test_fixedint(void **state);
|
||||
void test_numbers(void **state);
|
||||
void test_conversions(void **state);
|
||||
void test_nil(void **state);
|
||||
void test_boolean(void **state);
|
||||
void test_bin(void **state);
|
||||
void test_string(void **state);
|
||||
void test_array(void **state);
|
||||
void test_map(void **state);
|
||||
void test_ext(void **state);
|
||||
void test_obj(void **state);
|
||||
#ifndef CMP_NO_FLOAT
|
||||
void test_float_flip(void **state);
|
||||
#endif
|
||||
void test_skipping(void **state);
|
||||
void test_deprecated_limited_skipping(void **state);
|
||||
void test_errors(void **state);
|
||||
void test_version(void **state);
|
||||
|
||||
/* vi: set et ts=2 sw=2: */
|
||||
58
local_pod_repo/cmp/cmp/test/utils.c
Normal file
58
local_pod_repo/cmp/cmp/test/utils.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
void error_and_exit(const char *msg) {
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void errorf_and_exit(const char *msg, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, msg);
|
||||
vfprintf(stderr, msg, args);
|
||||
va_end(args);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char* _strdup(const char *s) {
|
||||
char *out = calloc(strlen(s) + 1, sizeof(char));
|
||||
|
||||
strcpy(out, s);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/* vi: set et ts=2 sw=2: */
|
||||
|
||||
52
local_pod_repo/cmp/cmp/test/utils.h
Normal file
52
local_pod_repo/cmp/cmp/test/utils.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UTILS_H__
|
||||
#define UTILS_H__
|
||||
|
||||
void error_and_exit(const char *msg);
|
||||
|
||||
#ifdef __GNUC__
|
||||
void errorf_and_exit(const char *msg, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
#else
|
||||
void errorf_and_exit(const char *msg, ...);
|
||||
#endif
|
||||
|
||||
char* _strdup(const char *s);
|
||||
|
||||
#ifndef strdup
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
32
local_pod_repo/msgpack-c/.gitignore
vendored
Normal file
32
local_pod_repo/msgpack-c/.gitignore
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# OS X
|
||||
.DS_Store
|
||||
|
||||
# Xcode
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
profile
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
|
||||
# Bundler
|
||||
.bundle
|
||||
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
|
||||
#
|
||||
# Note: if you ignore the Pods directory, make sure to uncomment
|
||||
# `pod install` in .travis.yml
|
||||
#
|
||||
# Pods/
|
||||
674
local_pod_repo/msgpack-c/LICENSE
Normal file
674
local_pod_repo/msgpack-c/LICENSE
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
35
local_pod_repo/msgpack-c/msgpack-c.podspec
Normal file
35
local_pod_repo/msgpack-c/msgpack-c.podspec
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# Be sure to run `pod lib lint toxcore.podspec' to ensure this is a
|
||||
# valid spec and remove all comments before submitting the spec.
|
||||
#
|
||||
# Any lines starting with a # are optional, but encouraged
|
||||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
|
||||
#
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "msgpack-c"
|
||||
s.version = "4.0.0"
|
||||
s.summary = "Cocoapods wrapper for msgpack-c"
|
||||
s.homepage = "https://github.com/Zoxcore/msgpack-c"
|
||||
s.license = 'GPLv3'
|
||||
s.author = "Zoff"
|
||||
s.source = {
|
||||
:git => "https://github.com/Zoxcore/msgpack-c.git",
|
||||
:tag => s.version.to_s,
|
||||
:submodules => true
|
||||
}
|
||||
|
||||
s.pod_target_xcconfig = { 'ENABLE_BITCODE' => 'NO', 'OTHER_LDFLAGS' => '-read_only_relocs suppress' }
|
||||
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.requires_arc = true
|
||||
|
||||
# Preserve the layout of headers in the msgpack-c directory
|
||||
#s.header_mappings_dir = 'msgpack-c/include'
|
||||
|
||||
s.source_files = 'msgpack-c/include/*h', 'msgpack-c/include/msgpack/*h', 'msgpack-c/src/*.c'
|
||||
#s.public_header_files = 'msgpack-c/include/*.h', 'msgpack-c/include/msgpack/*.h'
|
||||
#s.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '"${PODS_ROOT}"'}
|
||||
|
||||
end
|
||||
51
local_pod_repo/msgpack-c/msgpack-c/.gitignore
vendored
Normal file
51
local_pod_repo/msgpack-c/msgpack-c/.gitignore
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
# Files generated by the bootstrap script.
|
||||
/INSTALL
|
||||
/AUTHORS
|
||||
/ChangeLog
|
||||
/NEWS
|
||||
/README
|
||||
/ac/
|
||||
/aclocal.m4
|
||||
/autom4te.cache/
|
||||
/config.h.in
|
||||
/configure
|
||||
/msgpack_vc2008.sln
|
||||
/msgpack_vc2008.vcproj
|
||||
Makefile.in
|
||||
|
||||
# Files generated by the configure script.
|
||||
|
||||
/config.h
|
||||
/config.log
|
||||
/config.status
|
||||
/libtool
|
||||
/msgpack.pc
|
||||
/src/msgpack/version.h
|
||||
/src/msgpack/version.hpp
|
||||
/stamp-h1
|
||||
Makefile
|
||||
.deps
|
||||
.libs
|
||||
|
||||
# Files generated by make.
|
||||
*.o
|
||||
*.so
|
||||
*.lo
|
||||
*.la
|
||||
|
||||
# Files generated by make check.
|
||||
# TODO: Replace these with something like /test/*_test
|
||||
/test/buffer
|
||||
/test/cases
|
||||
/test/convert
|
||||
/test/fixint
|
||||
/test/fixint_c
|
||||
/test/msgpack_test
|
||||
/test/msgpackc_test
|
||||
/test/object
|
||||
/test/pack_unpack
|
||||
/test/pack_unpack_c
|
||||
/test/streaming
|
||||
/test/streaming_c
|
||||
/test/version
|
||||
/test/zone
|
||||
424
local_pod_repo/msgpack-c/msgpack-c/CHANGELOG.md
Normal file
424
local_pod_repo/msgpack-c/msgpack-c/CHANGELOG.md
Normal file
@@ -0,0 +1,424 @@
|
||||
# 2021-08-01 version 4.0.0
|
||||
* Fix and improve alignment logic (#962)
|
||||
* Fix iovec name conflict (#953)
|
||||
* Fix empty string print (#942)
|
||||
* Fix buffer ptr size (#899)
|
||||
* Fix UB. Check null pointer before using memcpy() (#890)
|
||||
* Improve CI environment (#885, #899)
|
||||
|
||||
## << breaking changes >>
|
||||
* Separate C part of the msgpack-c from C/C++ mixed msgpack-c (#876, #878)
|
||||
|
||||
|
||||
# 2020-06-05 version 3.3.0
|
||||
* Add json example for C (#870)
|
||||
* Add both header and body packing functions for C (#870)
|
||||
* Set default ref_size and chunk_size to vrefbuffer (#865)
|
||||
* Add examples (#861)
|
||||
* Improve build system (#839, #842)
|
||||
* Improve tests (#829)
|
||||
* Improve documents (#828)
|
||||
* Remove some warnings (#827, #851, #871)
|
||||
* Improve CI environment (#824, #831, #833, #834, #846, #860, 874)
|
||||
|
||||
# 2019-12-10 version 3.2.1
|
||||
* Fix snprintf return value checking (#821)
|
||||
* Remove some warnings (#819)
|
||||
* Fix fbuffer result checking (#812)
|
||||
* Fix temporary object handling (#807)
|
||||
* Improve cmake support (#804)
|
||||
* Fix invalid `int main` parameter (#800)
|
||||
* Improve supporting platform (#797, #817)
|
||||
* Fix ZLIB error handling (#795)
|
||||
* Remove unused variable (#793)
|
||||
* Improve integer overflow checking (#792)
|
||||
|
||||
# 2019-05-27 version 3.2.0
|
||||
|
||||
* Fix invalid include (#783)
|
||||
* Add timespec support (#781)
|
||||
* Fix unchecked fnprintf on C (#780)
|
||||
* Improve integer overflow checking on C (#776)
|
||||
* Fix warnings on `-Wconversion` (#770, #777, #784)
|
||||
* Fix invalid passed by value on aligned_zone_size_visitor (#764)
|
||||
* Improve windows support (#757, #779)
|
||||
* Fix msgpack::object size caluclation error (#754)
|
||||
* Fix memory error on example code (#753)
|
||||
* Fix redundant memory allocation on C (#747)
|
||||
* Fix msgpack::type::tuple base class conversion (#743)
|
||||
|
||||
# 2018-09-09 version 3.1.1
|
||||
|
||||
* Add force endian set functionality (#736)
|
||||
* Fix vrefbuffer memory management problem (#733)
|
||||
* Fix msvc specific problem (#731, #732)
|
||||
* Update boost from 1.61.0 to 1.68.0 (#730)
|
||||
* Fix msgpack_timestamp type mismatch bug (#726)
|
||||
|
||||
# 2018-08-10 version 3.1.0
|
||||
|
||||
* Improve documents (#687, #718)
|
||||
* Add fuzzer support (#689)
|
||||
* Fix msgpack::object union member access bug (#694)
|
||||
* Improve cross platform configuration (#704)
|
||||
* Fix out of range dereference bug of EXT (#705)
|
||||
* Add timestamp support. std::chrono::system_clock::time_point is mapped to TIMESTAMP (#706)
|
||||
* Add minimal timestamp support for C. The type `msgpack_timestamp` and the function `msgpack_object_to_timestamp()` are introduced (#707)
|
||||
* Improve MSGPACK_DEFINE family name confliction probability (#710)
|
||||
* Add no static-library build option (BUILD_SHARED_LIBS=ON) (#713, #717, #722)
|
||||
* Add header only cmake target (#721)
|
||||
* Add `std::byte` adaptor (#719)
|
||||
* Remove some warnings (#720)
|
||||
|
||||
# 2018-05-12 version 3.0.1
|
||||
|
||||
* Add fuzz directory to release tar ball (#686)
|
||||
* Add include file checking for X-Code (#683)
|
||||
|
||||
# 2018-05-09 version 3.0.0
|
||||
|
||||
## << breaking changes >>
|
||||
|
||||
* Change offset parameter updating rule. If parse error happens, offset is updated to the error position. (#639, #666)
|
||||
|
||||
## << other updates >>
|
||||
|
||||
* Improve cross platform configuration (#655, #677)
|
||||
* Improve build system (#647)
|
||||
* Improve user class adaptor (#645, #673)
|
||||
* Improve msgpack::object visitation logic (#676)
|
||||
* Remove some warnings (#641, 659)
|
||||
* Add `->` and `*` operators to object_handle (#635)
|
||||
* Improve CI environment (#631, #634, #643, #657, #662, #668)
|
||||
* Improve documents (#630, #661)
|
||||
* Refactoring (#670)
|
||||
* Add OSS-Fuzz support (#672, #674, #675, #678)
|
||||
|
||||
# 2017-08-04 version 2.1.5
|
||||
* Improve cross platform configuration (#624)
|
||||
* Add boost asio examples (including zlib) (#610)
|
||||
* Remove some warnings (#611)
|
||||
* Fix unpack visitor to treat float32/64 correctly (#613)
|
||||
* Improve documents (#616)
|
||||
* Fix alignment problem on some platform (#617, #518)
|
||||
* Fix conflict std::tuple, std::pair, and boost::fusion::sequence problem (#619)
|
||||
|
||||
# 2017-08-03 version 2.1.4 (Invalid)
|
||||
* See https://github.com/msgpack/msgpack-c/issues/623
|
||||
|
||||
# 2017-06-15 version 2.1.3
|
||||
* Improve build system (#603)
|
||||
* Add C++17 adaptors `std::optional` and `std::string_view`. (#607, #608)
|
||||
* Improve cross platform configuration (#601)
|
||||
* Remove some warnings (#599, #602, #605)
|
||||
|
||||
# 2017-06-07 version 2.1.2
|
||||
|
||||
* Improve documents (#565)
|
||||
* Fix empty map parse bug (#568)
|
||||
* Improve build system (#569, #570, #572, #579, #591, #592)
|
||||
* Remove some warnings (#574, #578, #586, #588)
|
||||
* Improve cross platform configuration (#577, #582)
|
||||
* Add cmake package config support (#580)
|
||||
* Fix streaming unpack bug (#585)
|
||||
|
||||
# 2017-02-04 version 2.1.1
|
||||
|
||||
* Fix unpacker's buffer management bug (#561)
|
||||
* Add boost string_view adaptor (#558)
|
||||
* Remove some warnings (#557, #559)
|
||||
* Improve coding style (#556)
|
||||
|
||||
# 2017-01-10 version 2.1.0
|
||||
|
||||
## << breaking changes >>
|
||||
|
||||
* Fix object internal data type is float if msgpack format is float32 (#531)
|
||||
|
||||
## << recommended changes >>
|
||||
|
||||
* Add `FLOAT64` type. Please use it instead of `DOUBLE` (#531)
|
||||
* Add `FLOAT32` type. Please use it instead of `FLOAT` (#531)
|
||||
|
||||
## << other updates >>
|
||||
|
||||
* Add iterator based parse/unpack function(experimental) (#553)
|
||||
* Add `[[deprecated]]` attribute for C++14 (#552)
|
||||
* Fix `msgpack_unpack()` return code (#548)
|
||||
* Fix integer overflow (#547, #549, #550)
|
||||
* Add example codes (#542)
|
||||
* Add MSGPACK_NVP. You can use not only variable name but also any strings (#535)
|
||||
* Fix and Improve build system (#532, #545)
|
||||
* Fix `gcc_atomic.hpp` include path (#529, #530)
|
||||
* Improve CI environment (#526)
|
||||
* Improve documents (#524)
|
||||
* Add msgpack_unpacker_next_with_size() function (#515)
|
||||
* Fix `as()` applying condition (#511)
|
||||
* Fix fbuffer write (#504)
|
||||
* Add gcc bug workaround (#499)
|
||||
* Improve object print (#497, #500, #505, #533)
|
||||
* Remove some warnings (#495, #506, #508, #513, #528, #538, #545)
|
||||
|
||||
# 2016-06-25 version 2.0.0
|
||||
|
||||
## << breaking changes >>
|
||||
|
||||
* Removed autotools support. Use cmake instead (#476, #479)
|
||||
* Removed pointer version of msgpack::unpack APIs. Use reference version instead (#453)
|
||||
* Removed MSGPACK_DISABLE_LEGACY_CONVERT. msgpack::object::convert(T*) is removed by default. Use msgpack::object::convert(T&) instead (#451)
|
||||
* Removed msgpacl::type::nil. Use nil_t or define MSGPACK_USE_LECACY_NIL (#444)
|
||||
* Removed std::string to msgpack::object conversion (#434)
|
||||
|
||||
## << recommended changes >>
|
||||
|
||||
* Replaced msgpack::unpacked with msgpack::object_handle. msgpack::unpacked is kept as a typedef of msgpack::object_handle. (#448)
|
||||
|
||||
## << other updates >>
|
||||
|
||||
* Add strict size checking adaptor. Relaxed tuple conversion (#489)
|
||||
* Fix and Improve example codes (#487)
|
||||
* Add C++/CLI support for nullptr (#481)
|
||||
* Update the boost libraries that are contained by msgpack-c (#475)
|
||||
* Fix gcc_atomic.hpp location (#474)
|
||||
* Add C-Style array support (#466, #488)
|
||||
* Fix include file dependency (#464)
|
||||
* Add a visitor version of unpack API (#461)
|
||||
* Fix JSON string conversion from "nil" to "null" (#458)
|
||||
* Fix and Improve build system (#455, #471, #473, #486, #491)
|
||||
* Fix comments (#452)
|
||||
* Fix unintentional msgpack::zone moving problem (#447)
|
||||
* Fix operator>> and << for msgpack::object (#443)
|
||||
* Fix C++03 msgpack::zone::clear() memory access violation bug (#441)
|
||||
* Fix TARGET_OS_IPHONE checking (#436)
|
||||
* Fix invalid front() call for empty container (#435)
|
||||
* Fix compile error on g++6 (C++11 only) (#426, #430)
|
||||
* Fix zone size expansion logic (#423)
|
||||
* Fix wrong hader file dependency (#421)
|
||||
* Fix msvc specific problem (#420)
|
||||
* Add v2 API support (#415)
|
||||
|
||||
# 2016-01-22 version 1.4.0
|
||||
|
||||
## << recommended changes >>
|
||||
|
||||
* Define [MSGPACK_DISABLE_LEGACY_NIL](https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_configure#msgpack_disable_legacy_nil-since-140), then `msgpack::type::nil` is replaced by with `msgpack::type::nil_t` (#408, #411, #412).
|
||||
Replace `msgpack::type::nil` with `msgpack::type::nil_t` in client codes.
|
||||
`msgpack::type::nil` will be removed on the version 2.0.0.
|
||||
* Define [MSGPACK_DISABLE_LEGACY_CONVERT](https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_configure#msgpack_disable_legacy_convert-since-140), then `msgpack::object::convert(T*)` is removed (#410).
|
||||
Replace calling `msgpack::bojectconvert(T*)` with `msgpack::bojectconvert(T&)` in client codes as follows:
|
||||
|
||||
```C++
|
||||
int i;
|
||||
obj.convert(&i); // before
|
||||
```
|
||||
|
||||
```C++
|
||||
int i;
|
||||
obj.convert(i); // after
|
||||
```
|
||||
|
||||
`msgpack::object::convert(T*)` will be removed on the version 2.0.0.
|
||||
|
||||
Define the macros above as follows when you compile C++ codes that use msgpack-c:
|
||||
|
||||
```
|
||||
g++ -Ipath_to_msgpack/include -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT your_code.cpp
|
||||
|
||||
```
|
||||
|
||||
You can compile existing codes without defining macros above but I recommend defining them and updating your codes to fix the issues #408, #411, #412, #399, and #410. It is also a good preparation for the version 2.0.0.
|
||||
|
||||
## << other updates >>
|
||||
|
||||
* Improve documents (#387, #407)
|
||||
* Remove C++ version library (#394, #402)
|
||||
* Add Doxyfile and ChangeLog to the distribution package (#397)
|
||||
* Add signed/unsigned char test to travis-ci (#398)
|
||||
* Remove some warnings (#400, #401, #409)
|
||||
* Fix endian checking. (#404)
|
||||
|
||||
# 2015-11-21 version 1.3.0
|
||||
|
||||
* Change the license from the Apache License Version 2.0 to the
|
||||
Boost Software License, Version 1.0.(#386)
|
||||
* Remove some warnings (#365)
|
||||
* Add std::reference_wrapper support(#373, #384)
|
||||
* Improve tests (#375, #378, #379, #380)
|
||||
* Fix msvc specific problem (#376, #383)
|
||||
* Fix typos (#381)
|
||||
|
||||
# 2015-09-04 version 1.2.0
|
||||
|
||||
## << breaking changes >>
|
||||
|
||||
* Change std::vector<unsigned char> and std::array<unsigned char>
|
||||
mapped to BIN instead of ARRAY (#243)
|
||||
* Remove redundant copy (#285)
|
||||
|
||||
|
||||
## << other updates >>
|
||||
|
||||
* Add array_ref to map to ARRAY (#243)
|
||||
* Add variant type and adaptor (#349)
|
||||
* Add object::convert_if_not_nil() (#357)
|
||||
* Fix invalid offset update (#354)
|
||||
* Add C++11 support on MSVC2015(#339, #347)
|
||||
* Fix and Improve build system (#346, #350, #361, #363)
|
||||
* Import Boost.Preprocessor as a part of msgpack-c (#312)
|
||||
* Fix OSX with libc++ specific errors (#334, #362)
|
||||
* Add customized containers support (#330)
|
||||
* Add std::unique_ptr and std::shared_ptr support (#329)
|
||||
* Add missing install files (#328)
|
||||
* Add shared/static library switching option (#316)
|
||||
* Improve no throw description on C++11 (#313)
|
||||
* Import Boost.Predef as a part of msgpack-c (#312)
|
||||
* Add map based serialize support (#306)
|
||||
* Add Boost.Fusion support (#305)
|
||||
* Add v4 format RAW support (#304)
|
||||
* Fix zbuffer with empty string problem (#303)
|
||||
* Add non default constructible class support (#302, #324, #327, #331, #332, #345)
|
||||
* Add inline keyword to function (template) (#299)
|
||||
* Add EXT type supporting classes (#292, #308)
|
||||
* Fix raw_ref != comparison (#290)
|
||||
* Add object deep copy (#288)
|
||||
* Remove some warnings (#284, #322, #323, #335)
|
||||
* Improve compiler version checking (#283)
|
||||
* Add return value to object::convert() (#282)
|
||||
* Improve move semantic support in C++11 (#279, #353)
|
||||
* Add Boost.StringRef support (#278)
|
||||
* Improve CI environment (#276, #294, #338)
|
||||
* Add converting to JSON (#274, #301)
|
||||
* Fix iOS specific problem (#270)
|
||||
* Improve doxtgen document generation (#269)
|
||||
* Add Boost.Optional support (#268)
|
||||
* Fix msvc specific problem (#267, #295)
|
||||
* Add base class serialization. (#265, #277)
|
||||
* Add and improve examples. (#264, #310, #311, #341, #342, #344)
|
||||
* Fix wiki URL. (#263)
|
||||
|
||||
# 2015-04-03 version 1.1.0
|
||||
|
||||
## << breaking changes >>
|
||||
|
||||
* Remove msgpack_fwd.hpp
|
||||
* Improve user types adaptation mechanism (#262)
|
||||
Since version 1.0.0, users need to obey the correct include order.
|
||||
However, it is very difficult to maintain the correct order in big
|
||||
projects. version 1.1.0 removed this order. Users don't need to
|
||||
care about include order. Migration guide from 1.0.x to 1.1.0 has
|
||||
been written. See https://github.com/msgpack/msgpack-c/wiki
|
||||
|
||||
|
||||
## << other updates >>
|
||||
|
||||
* Fix vector<bool> size check (#251)
|
||||
* Fix inttypes.h inclusion on MSVC (#257)
|
||||
* Support documents generation by Doxygen (#259)
|
||||
* Remove C99 style variable declaration (#253)
|
||||
* Improve documents (https://github.com/msgpack/msgpack-c/wiki)
|
||||
|
||||
# 2015-03-22 version 1.0.1:
|
||||
|
||||
* Fix compilation error on Mac 10.9 (#244)
|
||||
* Fix typos in documents (#240)
|
||||
* Update CHANGELOG.md for version 1.0.0 (#242)
|
||||
* Fix erb templates for the next code generation (#239)
|
||||
|
||||
# 2015-03-10 version 1.0.0:
|
||||
|
||||
* Support msgpack v5 format (str, bin, and ext) https://github.com/msgpack/msgpack/blob/master/spec.md (#142)
|
||||
* Support std::tuple, std::forward_list, std::array, std::unordered_set, std::unordered_map on C++11. tr1 unordered containers are still supported (#53, #130, #137, #154, #169)
|
||||
* Update msgpack-c as a header-only library on C++ (#142)
|
||||
* Move include directory (#142)
|
||||
* Update the name of float format family on msgpack::object from 'dec' to 'f64' (#194)
|
||||
* Remove existing elements on associative containers when unpacking (#127)
|
||||
* Add an API versioning functionality https://github.com/msgpack/msgpack-c/wiki/cpp_versioning (#139)
|
||||
* Add C++11 enum class support (#205)
|
||||
* Map std::vector<char> and std::array<char> to BIN (#100)
|
||||
* Map '\0' teminated char* and char const* to STR (#206)
|
||||
* Add the new parameter on unpacking functions and classes to limit msgpack's bytestream size (https://github.com/msgpack/msgpack-c/wiki/cpp_unpacker#limit-size-of-elements) (#175)
|
||||
* Add the copy or reference choosing function on unpack() and unpacker (https://github.com/msgpack/msgpack-c/wiki/cpp_unpacker#memory-management)
|
||||
* Add the new unpack() overloads for C++11 https://github.com/msgpack/msgpack-c/wiki/cpp_unpacker (#128)
|
||||
* Add a msgpack::object::with_zone (deep) copying function (#133, #163)
|
||||
* Remove the compile-time defined limit of msgpack nest level on C++ (#218)
|
||||
* Add the new unpack() overloads that use an existing zone (#201)
|
||||
* Add the range-based for loop support on msgpack object array and map (#203)
|
||||
* Add msgpack revision getter function for 'revision' (#237)
|
||||
* Support EXT for C (#118, #129)
|
||||
* Fix unpacking buffer allocation problem when malformed data is given (#160, #185)
|
||||
* Add dll exporting function on MSVC (#162)
|
||||
* Fix msgpack::zone::allocate_no_align(). Now it allocates the memory that is not aligned as expected (#171)
|
||||
* Improve documents (https://github.com/msgpack/msgpack-c/wiki)
|
||||
* Other bug fixes and refactoring: #62, #91, #95, #97, #107, #109, #113, #117, #119, #121, #122, #123, #126, #131, #136, #138, #140, #143, #145, #146, #150, #151, #152, #156, #157, #158, #161, #165, #170, #172, #179, #180, #181, #182, #183, #192, #195, #199, #200, #207, #211, #212, #219, #222, #224, #230, #231, #232, #233, #234, #235
|
||||
|
||||
# 2014-07-02 version 0.5.9:
|
||||
|
||||
* Support std::tr1 unordered containers by default (#51, #63, #68, #69)
|
||||
* Remove some warnings (#56)
|
||||
* Fix segmentation fault after malloc failures (#58, #59)
|
||||
* Fix alloc/dealloc mismatch (#52, #61)
|
||||
* Fix sample codes (#60, #64)
|
||||
* Support implicit conversion from integer to float/double (#54)
|
||||
* Improve documents (#45, #75, #82, #83)
|
||||
* Support CMake (#20, #87)
|
||||
* Remove Ruby dependencies in bootstrap (#86, #87)
|
||||
* Add FILE* buffer (#40)
|
||||
* Other bug fixes and refactoring: #39, #73, #77, #79, #80, #81, #84, #90
|
||||
|
||||
# 2013-12-23 version 0.5.8:
|
||||
|
||||
* Move to the new github repository msgpack/msgpack-c
|
||||
* Support the new deserialization specification
|
||||
* fixes the problem of unpack helpers for array and map with 32bit compilers (#37, #38)
|
||||
* Other bug fixes and refactoring: #46, #41, #36, #35, #33, #32, #30, #29, #28, #27, #26, #25, #8, #3
|
||||
* Update of documents: #23, #18, #17
|
||||
|
||||
# 2011-08-08 version 0.5.7:
|
||||
|
||||
* fixes compile error problem with llvm-gcc and Mac OS X Lion
|
||||
|
||||
# 2011-04-24 version 0.5.6:
|
||||
|
||||
* #42 fixes double-free problem on msgpack_unpacker_release_zone
|
||||
|
||||
# 2011-02-24 version 0.5.5:
|
||||
|
||||
* eliminates dependency of winsock2.h header
|
||||
* fixes msgpack_vc.postbuild.bat file
|
||||
* fixes some implicit cast warnings
|
||||
|
||||
# 2010-08-29 version 0.5.4:
|
||||
|
||||
* includes msgpack_vc2008.vcproj file in source package
|
||||
* fixes type::fix_int types
|
||||
|
||||
# 2010-08-27 version 0.5.3:
|
||||
|
||||
* adds type::fix_{u,}int{8,16,32,64} types
|
||||
* adds msgpack_pack_fix_{u,}int{8,16,32,64} functions
|
||||
* adds packer<Stream>::pack_fix_{u,}int{8,16,32,64} functions
|
||||
* fixes include paths
|
||||
|
||||
# 2010-07-14 version 0.5.2:
|
||||
|
||||
* type::raw::str(), operator==, operator!=, operator< and operator> are now const
|
||||
* generates version.h using AC_OUTPUT macro in ./configure
|
||||
|
||||
# 2010-07-06 version 0.5.1:
|
||||
|
||||
* Add msgpack_vrefbuffer_new and msgpack_vrefbuffer_free
|
||||
* Add msgpack_sbuffer_new and msgpack_sbuffer_free
|
||||
* Add msgpack_unpacker_next and msgpack_unpack_next
|
||||
* msgpack::unpack returns void
|
||||
* Add MSGPACK_VERSION{,_MAJOR,_MINOR} macros to check header version
|
||||
* Add msgpack_version{,_major,_minor} functions to check library version
|
||||
* ./configure supports --disable-cxx option not to build C++ API
|
||||
|
||||
# 2010-04-29 version 0.5.0:
|
||||
|
||||
* msgpack_object_type is changed. MSGPACK_OBJECT_NIL is now 0x00.
|
||||
* New safe streaming deserializer API.
|
||||
* Add object::object(const T&) and object::operator=(const T&)
|
||||
* Add operator==(object, const T&)
|
||||
* MSGPACK_DEFINE macro defines msgpack_object(object* obj, zone* z)
|
||||
* C++ programs doesn't need to link "msgpackc" library.
|
||||
333
local_pod_repo/msgpack-c/msgpack-c/CMakeLists.txt
Normal file
333
local_pod_repo/msgpack-c/msgpack-c/CMakeLists.txt
Normal file
@@ -0,0 +1,333 @@
|
||||
CMAKE_MINIMUM_REQUIRED (VERSION 2.8.12)
|
||||
|
||||
IF ((CMAKE_VERSION VERSION_GREATER 3.1) OR
|
||||
(CMAKE_VERSION VERSION_EQUAL 3.1))
|
||||
CMAKE_POLICY(SET CMP0054 NEW)
|
||||
ENDIF ()
|
||||
|
||||
PROJECT (msgpack)
|
||||
|
||||
FILE (READ ${CMAKE_CURRENT_SOURCE_DIR}/include/msgpack/version_master.h contents)
|
||||
STRING (REGEX MATCH "#define MSGPACK_VERSION_MAJOR *([0-9a-zA-Z_]*)" NULL_OUT ${contents})
|
||||
SET (VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||
STRING (REGEX MATCH "#define MSGPACK_VERSION_MINOR *([0-9a-zA-Z_]*)" NULL_OUT ${contents})
|
||||
SET (VERSION_MINOR ${CMAKE_MATCH_1})
|
||||
STRING (REGEX MATCH "#define MSGPACK_VERSION_REVISION *([0-9a-zA-Z_]*)" NULL_OUT ${contents})
|
||||
SET (VERSION_REVISION ${CMAKE_MATCH_1})
|
||||
SET (VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION})
|
||||
|
||||
LIST (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
SET (prefix ${CMAKE_INSTALL_PREFIX})
|
||||
SET (exec_prefix "\${prefix}")
|
||||
SET (libdir "\${exec_prefix}/lib")
|
||||
SET (includedir "\${prefix}/include")
|
||||
|
||||
OPTION (MSGPACK_32BIT "32bit compile" OFF)
|
||||
|
||||
INCLUDE(TestBigEndian)
|
||||
TEST_BIG_ENDIAN(BIGENDIAN)
|
||||
IF (BIGENDIAN)
|
||||
SET(MSGPACK_ENDIAN_BIG_BYTE 1)
|
||||
SET(MSGPACK_ENDIAN_LITTLE_BYTE 0)
|
||||
ELSE ()
|
||||
SET(MSGPACK_ENDIAN_BIG_BYTE 0)
|
||||
SET(MSGPACK_ENDIAN_LITTLE_BYTE 1)
|
||||
ENDIF ()
|
||||
|
||||
CONFIGURE_FILE (
|
||||
cmake/sysdep.h.in
|
||||
include/msgpack/sysdep.h
|
||||
@ONLY
|
||||
)
|
||||
|
||||
CONFIGURE_FILE (
|
||||
cmake/pack_template.h.in
|
||||
include/msgpack/pack_template.h
|
||||
@ONLY
|
||||
)
|
||||
|
||||
IF (APPLE)
|
||||
SET(CMAKE_MACOSX_RPATH ON)
|
||||
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
|
||||
IF ("${isSystemDir}" STREQUAL "-1")
|
||||
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
IF (MSGPACK_32BIT)
|
||||
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
||||
SET (CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}")
|
||||
SET (CMAKE_EXE_LINKER_FLAGS "-m32 ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
ELSEIF ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
||||
SET (CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}")
|
||||
SET (CMAKE_EXE_LINKER_FLAGS "-m32 ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
OPTION (MSGPACK_BUILD_EXAMPLES "Build msgpack examples." ON)
|
||||
|
||||
IF (MSGPACK_CHAR_SIGN)
|
||||
SET (CMAKE_C_FLAGS "-f${MSGPACK_CHAR_SIGN}-char ${CMAKE_C_FLAGS}")
|
||||
ENDIF ()
|
||||
|
||||
FIND_PACKAGE (GTest)
|
||||
FIND_PACKAGE (ZLIB)
|
||||
FIND_PACKAGE (Threads)
|
||||
IF (GTEST_FOUND AND ZLIB_FOUND AND THREADS_FOUND)
|
||||
OPTION (MSGPACK_BUILD_TESTS "Build msgpack tests." ON)
|
||||
OPTION (MSGPACK_GEN_COVERAGE "Enable running gcov to get a test coverage report." OFF)
|
||||
ENDIF ()
|
||||
|
||||
IF (DEFINED BUILD_SHARED_LIBS)
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
IF (DEFINED MSGPACK_ENABLE_SHARED AND NOT MSGPACK_ENABLE_SHARED)
|
||||
MESSAGE(WARNING "MSGPACK_ENABLE_SHARED is overridden to ON by BUILD_SHARED_LIBS")
|
||||
ENDIF ()
|
||||
SET (MSGPACK_ENABLE_SHARED ON)
|
||||
IF (DEFINED MSGPACK_ENABLE_STATIC AND MSGPACK_ENABLE_STATIC)
|
||||
MESSAGE(WARNING "MSGPACK_ENABLE_STATIC is overridden to OFF by BUILD_SHARED_LIBS")
|
||||
ENDIF ()
|
||||
SET (MSGPACK_ENABLE_STATIC OFF)
|
||||
ELSE ()
|
||||
IF (DEFINED MSGPACK_ENABLE_SHARED AND MSGPACK_ENABLE_SHARED)
|
||||
MESSAGE(WARNING "MSGPACK_ENABLE_SHARED is overridden to OFF by BUILD_SHARED_LIBS")
|
||||
ENDIF ()
|
||||
SET (MSGPACK_ENABLE_SHARED OFF)
|
||||
IF (DEFINED MSGPACK_ENABLE_STATIC AND NOT MSGPACK_ENABLE_STATIC)
|
||||
MESSAGE(WARNING "MSGPACK_ENABLE_STATIC is overridden to ON by BUILD_SHARED_LIBS")
|
||||
ENDIF ()
|
||||
SET (MSGPACK_ENABLE_STATIC ON)
|
||||
ENDIF ()
|
||||
ELSE ()
|
||||
IF (NOT DEFINED MSGPACK_ENABLE_SHARED)
|
||||
SET (MSGPACK_ENABLE_SHARED ON)
|
||||
ENDIF ()
|
||||
IF (NOT DEFINED MSGPACK_ENABLE_STATIC)
|
||||
SET (MSGPACK_ENABLE_STATIC ON)
|
||||
ENDIF ()
|
||||
SET (BUILD_SHARED_LIBS ${MSGPACK_ENABLE_SHARED})
|
||||
ENDIF ()
|
||||
|
||||
INCLUDE (Files.cmake)
|
||||
|
||||
CONFIGURE_FILE (
|
||||
msgpack.pc.in
|
||||
msgpack.pc
|
||||
@ONLY
|
||||
)
|
||||
|
||||
IF (MSGPACK_ENABLE_SHARED OR MSGPACK_ENABLE_STATIC)
|
||||
ADD_LIBRARY (msgpackc
|
||||
${msgpackc_SOURCES}
|
||||
${msgpackc_HEADERS}
|
||||
)
|
||||
|
||||
SET_TARGET_PROPERTIES (msgpackc PROPERTIES SOVERSION 2 VERSION 2.0.0)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES (msgpackc
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include/msgpack>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
ENDIF ()
|
||||
|
||||
|
||||
IF (MSGPACK_ENABLE_SHARED AND MSGPACK_ENABLE_STATIC)
|
||||
ADD_LIBRARY (msgpackc-static STATIC
|
||||
${msgpackc_SOURCES}
|
||||
${msgpackc_HEADERS}
|
||||
)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES (msgpackc-static
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include/msgpack>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
SET_TARGET_PROPERTIES (msgpackc-static PROPERTIES OUTPUT_NAME "msgpackc")
|
||||
|
||||
IF (MSGPACK_ENABLE_SHARED)
|
||||
IF (MSVC)
|
||||
SET_TARGET_PROPERTIES (msgpackc PROPERTIES IMPORT_SUFFIX "_import.lib")
|
||||
ELSEIF (MINGW)
|
||||
SET_TARGET_PROPERTIES (msgpackc PROPERTIES IMPORT_SUFFIX ".dll.a")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
IF (MSGPACK_GEN_COVERAGE)
|
||||
IF (NOT MSGPACK_BUILD_TESTS)
|
||||
MESSAGE(FATAL_ERROR "Coverage requires -DMSGPACK_BUILD_TESTS=ON")
|
||||
ENDIF ()
|
||||
STRING(TOUPPER "${CMAKE_BUILD_TYPE}" UPPER_CMAKE_BUILD_TYPE)
|
||||
IF (NOT "${UPPER_CMAKE_BUILD_TYPE}" STREQUAL "DEBUG")
|
||||
MESSAGE(FATAL_ERROR "Coverage requires -DCMAKE_BUILD_TYPE=Debug")
|
||||
ENDIF ()
|
||||
|
||||
INCLUDE(CodeCoverage)
|
||||
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_FLAGS}")
|
||||
|
||||
SETUP_TARGET_FOR_COVERAGE(coverage make coverage test)
|
||||
ENDIF ()
|
||||
|
||||
IF (MSGPACK_BUILD_TESTS)
|
||||
ENABLE_TESTING ()
|
||||
list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure")
|
||||
# MEMORYCHECK_COMMAND_OPTIONS needs to place prior to CTEST_MEMORYCHECK_COMMAND
|
||||
SET (MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --show-leak-kinds=definite,possible --error-exitcode=1")
|
||||
FIND_PROGRAM(CTEST_MEMORYCHECK_COMMAND NAMES valgrind)
|
||||
INCLUDE(Dart)
|
||||
ADD_SUBDIRECTORY (test)
|
||||
ENDIF ()
|
||||
|
||||
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
||||
IF (MSGPACK_ENABLE_SHARED OR MSGPACK_ENABLE_STATIC)
|
||||
SET_PROPERTY (TARGET msgpackc APPEND_STRING PROPERTY COMPILE_FLAGS " -Wall -Wextra -DPIC")
|
||||
ENDIF ()
|
||||
IF (MSGPACK_ENABLE_SHARED AND MSGPACK_ENABLE_STATIC)
|
||||
SET_PROPERTY (TARGET msgpackc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -Wall -Wextra" )
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
||||
IF (MSGPACK_ENABLE_SHARED OR MSGPACK_ENABLE_STATIC)
|
||||
SET_PROPERTY (TARGET msgpackc APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-mismatched-tags")
|
||||
ENDIF ()
|
||||
IF (MSGPACK_ENABLE_SHARED AND MSGPACK_ENABLE_STATIC)
|
||||
SET_PROPERTY (TARGET msgpackc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-mismatched-tags")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
|
||||
IF (CMAKE_C_FLAGS MATCHES "/W[0-4]")
|
||||
STRING(REGEX REPLACE "/W[0-4]" "/W3 /WX" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
ELSE ()
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3 /WX")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
|
||||
IF (CMAKE_C_FLAGS MATCHES "/W[0-4]")
|
||||
STRING(REGEX REPLACE "/W[0-4]" "/W3 /WX" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
ELSE ()
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3 /WX")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC90" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC10")
|
||||
SET_SOURCE_FILES_PROPERTIES(${msgpackc_SOURCES} PROPERTIES LANGUAGE C)
|
||||
ENDIF ()
|
||||
|
||||
IF ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "sparc")
|
||||
SET (CMAKE_C_FLAGS "-DMSGPACK_ZONE_ALIGN=8 ${CMAKE_C_FLAGS}")
|
||||
ENDIF ()
|
||||
|
||||
IF (NOT DEFINED CMAKE_INSTALL_BINDIR)
|
||||
SET(CMAKE_INSTALL_BINDIR bin)
|
||||
ENDIF ()
|
||||
|
||||
IF (NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
||||
SET(CMAKE_INSTALL_LIBDIR lib)
|
||||
ENDIF ()
|
||||
|
||||
IF (MSGPACK_BUILD_EXAMPLES)
|
||||
ADD_SUBDIRECTORY (example)
|
||||
ENDIF ()
|
||||
|
||||
IF (MSGPACK_ENABLE_SHARED OR MSGPACK_ENABLE_STATIC)
|
||||
SET (MSGPACK_INSTALLTARGETS msgpackc)
|
||||
ENDIF ()
|
||||
|
||||
IF (MSGPACK_ENABLE_SHARED AND MSGPACK_ENABLE_STATIC)
|
||||
LIST (APPEND MSGPACK_INSTALLTARGETS msgpackc-static)
|
||||
ENDIF ()
|
||||
|
||||
INSTALL (TARGETS ${MSGPACK_INSTALLTARGETS} EXPORT msgpack-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
FOREACH (file ${msgpackc_common_HEADERS})
|
||||
GET_FILENAME_COMPONENT (dir ${file} PATH)
|
||||
INSTALL (FILES ${file} DESTINATION ${CMAKE_INSTALL_PREFIX}/${dir})
|
||||
ENDFOREACH ()
|
||||
FOREACH (file ${msgpackc_configured_HEADERS})
|
||||
GET_FILENAME_COMPONENT (dir ${file} PATH)
|
||||
INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/${file} DESTINATION ${CMAKE_INSTALL_PREFIX}/${dir})
|
||||
ENDFOREACH ()
|
||||
IF (NOT MSVC)
|
||||
INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/msgpack.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
ENDIF ()
|
||||
|
||||
# Doxygen
|
||||
FIND_PACKAGE (Doxygen)
|
||||
IF (DOXYGEN_FOUND)
|
||||
LIST (APPEND Doxyfile_c_CONTENT
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "FILE_PATTERNS = *.h" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "OUTPUT_DIRECTORY = doc_c" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "INPUT = ${CMAKE_CURRENT_SOURCE_DIR}/include" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "EXTRACT_ALL = YES" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "PROJECT_NAME = \"MessagePack for C\"" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "STRIP_FROM_PATH = ${CMAKE_CURRENT_SOURCE_DIR}/include" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
|
||||
)
|
||||
IF (DOXYGEN_DOT_FOUND)
|
||||
LIST (APPEND Doxyfile_c_CONTENT
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "HAVE_DOT = YES" >> ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
|
||||
)
|
||||
ENDIF ()
|
||||
ADD_CUSTOM_TARGET (
|
||||
doxygen
|
||||
${Doxyfile_c_CONTENT}
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile_c
|
||||
VERBATIM
|
||||
)
|
||||
ENDIF ()
|
||||
|
||||
INCLUDE (CMakePackageConfigHelpers)
|
||||
|
||||
SET (CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/msgpack")
|
||||
|
||||
WRITE_BASIC_PACKAGE_VERSION_FILE (
|
||||
msgpack-config-version.cmake
|
||||
VERSION ${VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
IF (NOT CMAKE_VERSION VERSION_LESS 3.0)
|
||||
EXPORT (EXPORT msgpack-targets
|
||||
FILE "${CMAKE_CURRENT_BINARY_DIR}/msgpack-targets.cmake"
|
||||
)
|
||||
ENDIF ()
|
||||
|
||||
CONFIGURE_PACKAGE_CONFIG_FILE (msgpack-config.cmake.in
|
||||
msgpack-config.cmake
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
|
||||
)
|
||||
|
||||
INSTALL (EXPORT msgpack-targets
|
||||
FILE
|
||||
msgpack-targets.cmake
|
||||
DESTINATION
|
||||
"${CMAKE_INSTALL_CMAKEDIR}"
|
||||
)
|
||||
|
||||
INSTALL (
|
||||
FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/msgpack-config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/msgpack-config-version.cmake"
|
||||
DESTINATION
|
||||
"${CMAKE_INSTALL_CMAKEDIR}"
|
||||
)
|
||||
5
local_pod_repo/msgpack-c/msgpack-c/COPYING
Normal file
5
local_pod_repo/msgpack-c/msgpack-c/COPYING
Normal file
@@ -0,0 +1,5 @@
|
||||
Copyright (C) 2008-2015 FURUHASHI Sadayuki
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
1552
local_pod_repo/msgpack-c/msgpack-c/Doxyfile
Normal file
1552
local_pod_repo/msgpack-c/msgpack-c/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
41
local_pod_repo/msgpack-c/msgpack-c/Files.cmake
Normal file
41
local_pod_repo/msgpack-c/msgpack-c/Files.cmake
Normal file
@@ -0,0 +1,41 @@
|
||||
# Source files
|
||||
SET (msgpackc_SOURCES
|
||||
src/objectc.c
|
||||
src/unpack.c
|
||||
src/version.c
|
||||
src/vrefbuffer.c
|
||||
src/zone.c
|
||||
)
|
||||
|
||||
# Header files
|
||||
SET (msgpackc_common_HEADERS
|
||||
include/msgpack.h
|
||||
include/msgpack/fbuffer.h
|
||||
include/msgpack/gcc_atomic.h
|
||||
include/msgpack/object.h
|
||||
include/msgpack/pack.h
|
||||
include/msgpack/pack_define.h
|
||||
include/msgpack/sbuffer.h
|
||||
include/msgpack/timestamp.h
|
||||
include/msgpack/unpack.h
|
||||
include/msgpack/unpack_define.h
|
||||
include/msgpack/unpack_template.h
|
||||
include/msgpack/util.h
|
||||
include/msgpack/version.h
|
||||
include/msgpack/version_master.h
|
||||
include/msgpack/vrefbuffer.h
|
||||
include/msgpack/zbuffer.h
|
||||
include/msgpack/zone.h
|
||||
)
|
||||
|
||||
# Header files will configured
|
||||
SET (msgpackc_configured_HEADERS
|
||||
include/msgpack/pack_template.h
|
||||
include/msgpack/sysdep.h
|
||||
)
|
||||
|
||||
# All header files
|
||||
LIST (APPEND msgpackc_HEADERS
|
||||
${msgpackc_common_HEADERS}
|
||||
${msgpackc_configured_HEADERS}
|
||||
)
|
||||
23
local_pod_repo/msgpack-c/msgpack-c/LICENSE_1_0.txt
Normal file
23
local_pod_repo/msgpack-c/msgpack-c/LICENSE_1_0.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
14
local_pod_repo/msgpack-c/msgpack-c/NOTICE
Normal file
14
local_pod_repo/msgpack-c/msgpack-c/NOTICE
Normal file
@@ -0,0 +1,14 @@
|
||||
This product bundles Boost Predef and Boost Preprocessor.
|
||||
They are distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
For details, see the following files:
|
||||
|
||||
external/boost/predef
|
||||
include/msgpack/predef.h
|
||||
include/msgpack/predef/*
|
||||
|
||||
external/boost/preprocessor
|
||||
include/msgpack/preprocessor.hpp
|
||||
include/msgpack/preprocessor/*
|
||||
193
local_pod_repo/msgpack-c/msgpack-c/QUICKSTART-C.md
Normal file
193
local_pod_repo/msgpack-c/msgpack-c/QUICKSTART-C.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# Implementation Status
|
||||
|
||||
The serialization library is production-ready.
|
||||
|
||||
Currently, RPC implementation is not available.
|
||||
|
||||
# Install
|
||||
|
||||
## Install with package manager
|
||||
|
||||
### MacOS with MacPorts
|
||||
|
||||
On MacOS, you can install MessagePack for C using MacPorts.
|
||||
|
||||
```
|
||||
$ sudo port install msgpack
|
||||
```
|
||||
|
||||
You might need to run `sudo port selfupdate` before installing to update the package repository.
|
||||
|
||||
You can also install via Homebrew.
|
||||
|
||||
```
|
||||
$ brew install msgpack
|
||||
```
|
||||
|
||||
### FreeBSD with Ports Collection
|
||||
|
||||
On FreeBSD, you can use Ports Collection. Install [net/msgpack](http://www.freebsd.org/cgi/cvsweb.cgi/ports/devel/msgpack/) package.
|
||||
|
||||
### Gentoo Linux with Portage
|
||||
|
||||
On Gentoo Linux, you can use emerge. Install [dev-libs/msgpack](http://gentoo-portage.com/dev-libs/msgpack) package.
|
||||
|
||||
### Windows with vcpkg
|
||||
|
||||
There are several package managers available, and vcpkg is typical.
|
||||
|
||||
```
|
||||
$ vcpkg install msgpack:x64-windows
|
||||
```
|
||||
## Install with source code
|
||||
|
||||
### Build with cmake
|
||||
|
||||
You need to install cmake (2.8.12 or higher) first.
|
||||
|
||||
```
|
||||
$ git clone https://github.com/msgpack/msgpack-c.git
|
||||
$ cd msgpack-c
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
$ cmake --build .
|
||||
$ cmake --build . --target install
|
||||
```
|
||||
### Build with autotools
|
||||
|
||||
In versions 1.4.2 and below, you can use `autotools` to build on UNIX-like platforms.
|
||||
```
|
||||
$ wget https://github.com/msgpack/msgpack-c/archive/cpp-1.3.0.tar.gz
|
||||
$ tar zxvf msgpack-1.3.0.tar.gz
|
||||
$ cd msgpack-1.3.0
|
||||
$ ./bootstrap # If the 'configure' script already exists, you can omit this step.
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
# Serialization QuickStart for C
|
||||
|
||||
## First program
|
||||
|
||||
Include `msgpack.h` header and link `msgpack` library to use MessagePack on your program.
|
||||
|
||||
```c
|
||||
#include <msgpack.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
|
||||
/* creates buffer and serializer instance. */
|
||||
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
|
||||
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
|
||||
|
||||
/* serializes ["Hello", "MessagePack"]. */
|
||||
msgpack_pack_array(pk, 2);
|
||||
msgpack_pack_bin(pk, 5);
|
||||
msgpack_pack_bin_body(pk, "Hello", 5);
|
||||
msgpack_pack_bin(pk, 11);
|
||||
msgpack_pack_bin_body(pk, "MessagePack", 11);
|
||||
|
||||
/* deserializes it. */
|
||||
msgpack_unpacked msg;
|
||||
msgpack_unpacked_init(&msg);
|
||||
msgpack_unpack_return ret = msgpack_unpack_next(&msg, buffer->data, buffer->size, NULL);
|
||||
|
||||
/* prints the deserialized object. */
|
||||
msgpack_object obj = msg.data;
|
||||
msgpack_object_print(stdout, obj); /*=> ["Hello", "MessagePack"] */
|
||||
|
||||
/* cleaning */
|
||||
msgpack_unpacked_destroy(&msg);
|
||||
msgpack_sbuffer_free(buffer);
|
||||
msgpack_packer_free(pk);
|
||||
}
|
||||
```
|
||||
|
||||
## Simple program with a loop
|
||||
|
||||
```c
|
||||
#include <msgpack.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
|
||||
/* creates buffer and serializer instance. */
|
||||
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
|
||||
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
|
||||
|
||||
int j;
|
||||
|
||||
for(j = 0; j<23; j++) {
|
||||
/* NB: the buffer needs to be cleared on each iteration */
|
||||
msgpack_sbuffer_clear(buffer);
|
||||
|
||||
/* serializes ["Hello", "MessagePack"]. */
|
||||
msgpack_pack_array(pk, 3);
|
||||
msgpack_pack_bin(pk, 5);
|
||||
msgpack_pack_bin_body(pk, "Hello", 5);
|
||||
msgpack_pack_bin(pk, 11);
|
||||
msgpack_pack_bin_body(pk, "MessagePack", 11);
|
||||
msgpack_pack_int(pk, j);
|
||||
|
||||
/* deserializes it. */
|
||||
msgpack_unpacked msg;
|
||||
msgpack_unpacked_init(&msg);
|
||||
msgpack_unpack_return ret = msgpack_unpack_next(&msg, buffer->data, buffer->size, NULL);
|
||||
|
||||
/* prints the deserialized object. */
|
||||
msgpack_object obj = msg.data;
|
||||
msgpack_object_print(stdout, obj); /*=> ["Hello", "MessagePack"] */
|
||||
msgpack_unpacked_destroy(&msg);
|
||||
puts("");
|
||||
}
|
||||
|
||||
/* cleaning */
|
||||
msgpack_sbuffer_free(buffer);
|
||||
msgpack_packer_free(pk);
|
||||
}
|
||||
```
|
||||
|
||||
## Streaming feature
|
||||
|
||||
```c
|
||||
#include <msgpack.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
/* serializes multiple objects using msgpack_packer. */
|
||||
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
|
||||
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
|
||||
msgpack_pack_int(pk, 1);
|
||||
msgpack_pack_int(pk, 2);
|
||||
msgpack_pack_int(pk, 3);
|
||||
|
||||
/* deserializes these objects using msgpack_unpacker. */
|
||||
msgpack_unpacker pac;
|
||||
msgpack_unpacker_init(&pac, MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
|
||||
|
||||
/* feeds the buffer. */
|
||||
msgpack_unpacker_reserve_buffer(&pac, buffer->size);
|
||||
memcpy(msgpack_unpacker_buffer(&pac), buffer->data, buffer->size);
|
||||
msgpack_unpacker_buffer_consumed(&pac, buffer->size);
|
||||
|
||||
/* now starts streaming deserialization. */
|
||||
msgpack_unpacked result;
|
||||
msgpack_unpacked_init(&result);
|
||||
|
||||
while(msgpack_unpacker_next(&pac, &result)) {
|
||||
msgpack_object_print(stdout, result.data);
|
||||
puts("");
|
||||
}
|
||||
|
||||
/* results:
|
||||
* $ gcc stream.cc -lmsgpackc -o stream
|
||||
* $ ./stream
|
||||
* 1
|
||||
* 2
|
||||
* 3
|
||||
*/
|
||||
}
|
||||
```
|
||||
139
local_pod_repo/msgpack-c/msgpack-c/README.md
Normal file
139
local_pod_repo/msgpack-c/msgpack-c/README.md
Normal file
@@ -0,0 +1,139 @@
|
||||
`msgpack` for C
|
||||
===================
|
||||
|
||||
Version 4.0.0 [](https://github.com/msgpack/msgpack-c/actions) [](https://ci.appveyor.com/project/redboltz/msgpack-c/branch/c_master)
|
||||
[](https://codecov.io/gh/msgpack/msgpack-c/branch/c_master)
|
||||
|
||||
It's like JSON but smaller and faster.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
[MessagePack](http://msgpack.org/) is an efficient binary serialization
|
||||
format, which lets you exchange data among multiple languages like JSON,
|
||||
except that it's faster and smaller. Small integers are encoded into a
|
||||
single byte and short strings require only one extra byte in
|
||||
addition to the strings themselves.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```c
|
||||
#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_str(&pk, 7);
|
||||
msgpack_pack_str_body(&pk, "example", 7);
|
||||
|
||||
/* deserialize the buffer into msgpack_object instance. */
|
||||
/* deserialized object is valid during the msgpack_zone instance alive. */
|
||||
msgpack_zone mempool;
|
||||
msgpack_zone_init(&mempool, 2048);
|
||||
|
||||
msgpack_object deserialized;
|
||||
msgpack_unpack(sbuf.data, sbuf.size, NULL, &mempool, &deserialized);
|
||||
|
||||
/* print the deserialized object. */
|
||||
msgpack_object_print(stdout, deserialized);
|
||||
puts("");
|
||||
|
||||
msgpack_zone_destroy(&mempool);
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
See [`QUICKSTART-C.md`](./QUICKSTART-C.md) for more details.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
### Building and Installing
|
||||
|
||||
#### Install from git repository
|
||||
|
||||
##### Using the Terminal (CLI)
|
||||
|
||||
You will need:
|
||||
|
||||
- `gcc >= 4.1.0`
|
||||
- `cmake >= 2.8.0`
|
||||
|
||||
How to build:
|
||||
|
||||
$ git clone https://github.com/msgpack/msgpack-c.git
|
||||
$ cd msgpack-c
|
||||
$ git checkout c_master
|
||||
$ cmake .
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
How to run tests:
|
||||
|
||||
In order to run tests you must have the [GoogleTest](https://github.com/google/googletest) framework installed. If you do not currently have it, install it and re-run `cmake`.
|
||||
Then:
|
||||
|
||||
$ make test
|
||||
|
||||
When you use the C part of `msgpack-c`, you need to build and link the library. By default, both static/shared libraries are built. If you want to build only static library, set `BUILD_SHARED_LIBS=OFF` to cmake. If you want to build only shared library, set `BUILD_SHARED_LIBS=ON`.
|
||||
|
||||
#### GUI on Windows
|
||||
|
||||
Clone msgpack-c git repository.
|
||||
|
||||
$ git clone https://github.com/msgpack/msgpack-c.git
|
||||
|
||||
or using GUI git client.
|
||||
|
||||
e.g.) tortoise git https://code.google.com/p/tortoisegit/
|
||||
|
||||
1. Checkout to c_master branch
|
||||
|
||||
2. Launch [cmake GUI client](http://www.cmake.org/cmake/resources/software.html).
|
||||
|
||||
3. Set 'Where is the source code:' text box and 'Where to build
|
||||
the binaries:' text box.
|
||||
|
||||
4. Click 'Configure' button.
|
||||
|
||||
5. Choose your Visual Studio version.
|
||||
|
||||
6. Click 'Generate' button.
|
||||
|
||||
7. Open the created msgpack.sln on Visual Studio.
|
||||
|
||||
8. Build all.
|
||||
|
||||
### Documentation
|
||||
|
||||
You can get additional information including the tutorial on the
|
||||
[wiki](https://github.com/msgpack/msgpack-c/wiki).
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
`msgpack-c` is developed on GitHub at [msgpack/msgpack-c](https://github.com/msgpack/msgpack-c).
|
||||
To report an issue or send a pull request, use the
|
||||
[issue tracker](https://github.com/msgpack/msgpack-c/issues).
|
||||
|
||||
Here's the list of [great contributors](https://github.com/msgpack/msgpack-c/graphs/contributors).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
`msgpack-c` is licensed under the Boost Software License, Version 1.0. See
|
||||
the [`LICENSE_1_0.txt`](./LICENSE_1_0.txt) file for details.
|
||||
43
local_pod_repo/msgpack-c/msgpack-c/appveyor.yml
Normal file
43
local_pod_repo/msgpack-c/msgpack-c/appveyor.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
version: 4.0.0.{build}
|
||||
|
||||
branches:
|
||||
only:
|
||||
- c_master
|
||||
|
||||
image:
|
||||
- Visual Studio 2015
|
||||
environment:
|
||||
matrix:
|
||||
- msvc: '"Visual Studio 10 2010"'
|
||||
- msvc: '"Visual Studio 11 2012"'
|
||||
- msvc: '"Visual Studio 12 2013"'
|
||||
- msvc: '"Visual Studio 14 2015"'
|
||||
build_script:
|
||||
- appveyor DownloadFile https://github.com/google/googletest/archive/release-1.7.0.zip -FileName googletest-release-1.7.0.zip
|
||||
- 7z x googletest-release-1.7.0.zip > NUL
|
||||
- cd googletest-release-1.7.0
|
||||
- md build
|
||||
- cd build
|
||||
- cmake -G %msvc% -DBUILD_SHARED_LIBS=ON -DCMAKE_CXX_FLAGS=/D_VARIADIC_MAX=10 ..
|
||||
- cmake --build . --config Release
|
||||
- cd ..
|
||||
- cd ..
|
||||
- appveyor DownloadFile http://zlib.net/zlib-1.2.11.tar.gz -FileName zlib-1.2.11.tar.gz
|
||||
- 7z x zlib-1.2.11.tar.gz > NUL
|
||||
- 7z x zlib-1.2.11.tar > NUL
|
||||
- cd zlib-1.2.11
|
||||
- md build
|
||||
- cd build
|
||||
- cmake -G %msvc% ..
|
||||
- cmake --build . --config Release
|
||||
- copy zconf.h ..
|
||||
- cd ..
|
||||
- cd ..
|
||||
- md build
|
||||
- cd build
|
||||
- cmake -G %msvc% -DGTEST_LIBRARY=%APPVEYOR_BUILD_FOLDER%\googletest-release-1.7.0\build\Release\gtest.lib -DGTEST_MAIN_LIBRARY=%APPVEYOR_BUILD_FOLDER%\googletest-release-1.7.0\build\Release\gtest_main.lib -DGTEST_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER%\googletest-release-1.7.0\include -DZLIB_LIBRARY=%APPVEYOR_BUILD_FOLDER%\zlib-1.2.11\build\Release\zlib.lib -DZLIB_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER%\zlib-1.2.11 -DCMAKE_CXX_FLAGS='"/D_VARIADIC_MAX=10 /EHsc"' ..
|
||||
- cmake --build . --config Release -v
|
||||
|
||||
test_script:
|
||||
- set PATH=%PATH%;%APPVEYOR_BUILD_FOLDER%\googletest-release-1.7.0\build\Release;%APPVEYOR_BUILD_FOLDER%\zlib-1.2.11\build\Release;%APPVEYOR_BUILD_FOLDER%\build\release
|
||||
- ctest -V
|
||||
36
local_pod_repo/msgpack-c/msgpack-c/codecov.yml
Normal file
36
local_pod_repo/msgpack-c/msgpack-c/codecov.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
codecov:
|
||||
notify:
|
||||
require_ci_to_pass: yes
|
||||
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "70...100"
|
||||
|
||||
status:
|
||||
project: yes
|
||||
patch: yes
|
||||
changes: no
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: no
|
||||
macro: no
|
||||
|
||||
comment:
|
||||
layout: "header, diff"
|
||||
behavior: default
|
||||
require_changes: no
|
||||
|
||||
ignore:
|
||||
- "test"
|
||||
- "fuzz"
|
||||
- "erb"
|
||||
- "ci"
|
||||
- "cmake"
|
||||
- "examle"
|
||||
- "external"
|
||||
- "usr"
|
||||
24
local_pod_repo/msgpack-c/msgpack-c/include/msgpack.h
Normal file
24
local_pod_repo/msgpack-c/msgpack-c/include/msgpack.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* MessagePack for C
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
/**
|
||||
* @defgroup msgpack MessagePack C
|
||||
* @{
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "msgpack/util.h"
|
||||
#include "msgpack/object.h"
|
||||
#include "msgpack/zone.h"
|
||||
#include "msgpack/pack.h"
|
||||
#include "msgpack/unpack.h"
|
||||
#include "msgpack/sbuffer.h"
|
||||
#include "msgpack/vrefbuffer.h"
|
||||
#include "msgpack/msgpack_version.h"
|
||||
|
||||
42
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/fbuffer.h
Normal file
42
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/fbuffer.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* MessagePack for C FILE* buffer adaptor
|
||||
*
|
||||
* Copyright (C) 2013 Vladimir Volodko
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_FBUFFER_H
|
||||
#define MSGPACK_FBUFFER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msgpack_fbuffer FILE* buffer
|
||||
* @ingroup msgpack_buffer
|
||||
* @{
|
||||
*/
|
||||
|
||||
static inline int msgpack_fbuffer_write(void* data, const char* buf, size_t len)
|
||||
{
|
||||
assert(buf || len == 0);
|
||||
if(!buf) return 0;
|
||||
|
||||
return (1 == fwrite(buf, len, 1, (FILE *)data)) ? 0 : -1;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/fbuffer.h */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef MSGPACK_GCC_ATOMIC_H
|
||||
#define MSGPACK_GCC_ATOMIC_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int _msgpack_atomic_counter_t;
|
||||
|
||||
int _msgpack_sync_decr_and_fetch(volatile _msgpack_atomic_counter_t* ptr);
|
||||
int _msgpack_sync_incr_and_fetch(volatile _msgpack_atomic_counter_t* ptr);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // MSGPACK_GCC_ATOMIC_H
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* MessagePack for C version information
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_VERSION_H
|
||||
#define MSGPACK_VERSION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
const char* msgpack_version(void);
|
||||
MSGPACK_DLLEXPORT
|
||||
int msgpack_version_major(void);
|
||||
MSGPACK_DLLEXPORT
|
||||
int msgpack_version_minor(void);
|
||||
MSGPACK_DLLEXPORT
|
||||
int msgpack_version_revision(void);
|
||||
|
||||
#include "version_master.h"
|
||||
|
||||
#define MSGPACK_STR(v) #v
|
||||
#define MSGPACK_VERSION_I(maj, min, rev) MSGPACK_STR(maj) "." MSGPACK_STR(min) "." MSGPACK_STR(rev)
|
||||
|
||||
#define MSGPACK_VERSION MSGPACK_VERSION_I(MSGPACK_VERSION_MAJOR, MSGPACK_VERSION_MINOR, MSGPACK_VERSION_REVISION)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/version.h */
|
||||
|
||||
118
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/object.h
Normal file
118
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/object.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* MessagePack for C dynamic typing routine
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_OBJECT_H
|
||||
#define MSGPACK_OBJECT_H
|
||||
|
||||
#include "zone.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msgpack_object Dynamically typed object
|
||||
* @ingroup msgpack
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
MSGPACK_OBJECT_NIL = 0x00,
|
||||
MSGPACK_OBJECT_BOOLEAN = 0x01,
|
||||
MSGPACK_OBJECT_POSITIVE_INTEGER = 0x02,
|
||||
MSGPACK_OBJECT_NEGATIVE_INTEGER = 0x03,
|
||||
MSGPACK_OBJECT_FLOAT32 = 0x0a,
|
||||
MSGPACK_OBJECT_FLOAT64 = 0x04,
|
||||
MSGPACK_OBJECT_FLOAT = 0x04,
|
||||
#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
|
||||
MSGPACK_OBJECT_DOUBLE = MSGPACK_OBJECT_FLOAT, /* obsolete */
|
||||
#endif /* MSGPACK_USE_LEGACY_NAME_AS_FLOAT */
|
||||
MSGPACK_OBJECT_STR = 0x05,
|
||||
MSGPACK_OBJECT_ARRAY = 0x06,
|
||||
MSGPACK_OBJECT_MAP = 0x07,
|
||||
MSGPACK_OBJECT_BIN = 0x08,
|
||||
MSGPACK_OBJECT_EXT = 0x09
|
||||
} msgpack_object_type;
|
||||
|
||||
|
||||
struct msgpack_object;
|
||||
struct msgpack_object_kv;
|
||||
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
struct msgpack_object* ptr;
|
||||
} msgpack_object_array;
|
||||
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
struct msgpack_object_kv* ptr;
|
||||
} msgpack_object_map;
|
||||
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
const char* ptr;
|
||||
} msgpack_object_str;
|
||||
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
const char* ptr;
|
||||
} msgpack_object_bin;
|
||||
|
||||
typedef struct {
|
||||
int8_t type;
|
||||
uint32_t size;
|
||||
const char* ptr;
|
||||
} msgpack_object_ext;
|
||||
|
||||
typedef union {
|
||||
bool boolean;
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
|
||||
double dec; /* obsolete*/
|
||||
#endif /* MSGPACK_USE_LEGACY_NAME_AS_FLOAT */
|
||||
double f64;
|
||||
msgpack_object_array array;
|
||||
msgpack_object_map map;
|
||||
msgpack_object_str str;
|
||||
msgpack_object_bin bin;
|
||||
msgpack_object_ext ext;
|
||||
} msgpack_object_union;
|
||||
|
||||
typedef struct msgpack_object {
|
||||
msgpack_object_type type;
|
||||
msgpack_object_union via;
|
||||
} msgpack_object;
|
||||
|
||||
typedef struct msgpack_object_kv {
|
||||
msgpack_object key;
|
||||
msgpack_object val;
|
||||
} msgpack_object_kv;
|
||||
|
||||
#if !defined(_KERNEL_MODE)
|
||||
MSGPACK_DLLEXPORT
|
||||
void msgpack_object_print(FILE* out, msgpack_object o);
|
||||
#endif
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
int msgpack_object_print_buffer(char *buffer, size_t buffer_size, msgpack_object o);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
bool msgpack_object_equal(const msgpack_object x, const msgpack_object y);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/object.h */
|
||||
174
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/pack.h
Normal file
174
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/pack.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* MessagePack for C packing routine
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_PACK_H
|
||||
#define MSGPACK_PACK_H
|
||||
|
||||
#include "pack_define.h"
|
||||
#include "object.h"
|
||||
#include "timestamp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msgpack_buffer Buffers
|
||||
* @ingroup msgpack
|
||||
* @{
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup msgpack_pack Serializer
|
||||
* @ingroup msgpack
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef int (*msgpack_packer_write)(void* data, const char* buf, size_t len);
|
||||
|
||||
typedef struct msgpack_packer {
|
||||
void* data;
|
||||
msgpack_packer_write callback;
|
||||
} msgpack_packer;
|
||||
|
||||
static void msgpack_packer_init(msgpack_packer* pk, void* data, msgpack_packer_write callback);
|
||||
|
||||
static msgpack_packer* msgpack_packer_new(void* data, msgpack_packer_write callback);
|
||||
static void msgpack_packer_free(msgpack_packer* pk);
|
||||
|
||||
static int msgpack_pack_char(msgpack_packer* pk, char d);
|
||||
|
||||
static int msgpack_pack_signed_char(msgpack_packer* pk, signed char d);
|
||||
static int msgpack_pack_short(msgpack_packer* pk, short d);
|
||||
static int msgpack_pack_int(msgpack_packer* pk, int d);
|
||||
static int msgpack_pack_long(msgpack_packer* pk, long d);
|
||||
static int msgpack_pack_long_long(msgpack_packer* pk, long long d);
|
||||
static int msgpack_pack_unsigned_char(msgpack_packer* pk, unsigned char d);
|
||||
static int msgpack_pack_unsigned_short(msgpack_packer* pk, unsigned short d);
|
||||
static int msgpack_pack_unsigned_int(msgpack_packer* pk, unsigned int d);
|
||||
static int msgpack_pack_unsigned_long(msgpack_packer* pk, unsigned long d);
|
||||
static int msgpack_pack_unsigned_long_long(msgpack_packer* pk, unsigned long long d);
|
||||
|
||||
static int msgpack_pack_uint8(msgpack_packer* pk, uint8_t d);
|
||||
static int msgpack_pack_uint16(msgpack_packer* pk, uint16_t d);
|
||||
static int msgpack_pack_uint32(msgpack_packer* pk, uint32_t d);
|
||||
static int msgpack_pack_uint64(msgpack_packer* pk, uint64_t d);
|
||||
static int msgpack_pack_int8(msgpack_packer* pk, int8_t d);
|
||||
static int msgpack_pack_int16(msgpack_packer* pk, int16_t d);
|
||||
static int msgpack_pack_int32(msgpack_packer* pk, int32_t d);
|
||||
static int msgpack_pack_int64(msgpack_packer* pk, int64_t d);
|
||||
|
||||
static int msgpack_pack_fix_uint8(msgpack_packer* pk, uint8_t d);
|
||||
static int msgpack_pack_fix_uint16(msgpack_packer* pk, uint16_t d);
|
||||
static int msgpack_pack_fix_uint32(msgpack_packer* pk, uint32_t d);
|
||||
static int msgpack_pack_fix_uint64(msgpack_packer* pk, uint64_t d);
|
||||
static int msgpack_pack_fix_int8(msgpack_packer* pk, int8_t d);
|
||||
static int msgpack_pack_fix_int16(msgpack_packer* pk, int16_t d);
|
||||
static int msgpack_pack_fix_int32(msgpack_packer* pk, int32_t d);
|
||||
static int msgpack_pack_fix_int64(msgpack_packer* pk, int64_t d);
|
||||
|
||||
static int msgpack_pack_float(msgpack_packer* pk, float d);
|
||||
static int msgpack_pack_double(msgpack_packer* pk, double d);
|
||||
|
||||
static int msgpack_pack_nil(msgpack_packer* pk);
|
||||
static int msgpack_pack_true(msgpack_packer* pk);
|
||||
static int msgpack_pack_false(msgpack_packer* pk);
|
||||
|
||||
static int msgpack_pack_array(msgpack_packer* pk, size_t n);
|
||||
|
||||
static int msgpack_pack_map(msgpack_packer* pk, size_t n);
|
||||
|
||||
static int msgpack_pack_str(msgpack_packer* pk, size_t l);
|
||||
static int msgpack_pack_str_body(msgpack_packer* pk, const void* b, size_t l);
|
||||
static int msgpack_pack_str_with_body(msgpack_packer* pk, const void* b, size_t l);
|
||||
|
||||
static int msgpack_pack_v4raw(msgpack_packer* pk, size_t l);
|
||||
static int msgpack_pack_v4raw_body(msgpack_packer* pk, const void* b, size_t l);
|
||||
|
||||
static int msgpack_pack_bin(msgpack_packer* pk, size_t l);
|
||||
static int msgpack_pack_bin_body(msgpack_packer* pk, const void* b, size_t l);
|
||||
static int msgpack_pack_bin_with_body(msgpack_packer* pk, const void* b, size_t l);
|
||||
|
||||
static int msgpack_pack_ext(msgpack_packer* pk, size_t l, int8_t type);
|
||||
static int msgpack_pack_ext_body(msgpack_packer* pk, const void* b, size_t l);
|
||||
static int msgpack_pack_ext_with_body(msgpack_packer* pk, const void* b, size_t l, int8_t type);
|
||||
|
||||
static int msgpack_pack_timestamp(msgpack_packer* pk, const msgpack_timestamp* d);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
int msgpack_pack_object(msgpack_packer* pk, msgpack_object d);
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#define msgpack_pack_inline_func(name) \
|
||||
inline int msgpack_pack ## name
|
||||
|
||||
#define msgpack_pack_inline_func_cint(name) \
|
||||
inline int msgpack_pack ## name
|
||||
|
||||
#define msgpack_pack_inline_func_fixint(name) \
|
||||
inline int msgpack_pack_fix ## name
|
||||
|
||||
#define msgpack_pack_user msgpack_packer*
|
||||
|
||||
#define msgpack_pack_append_buffer(user, buf, len) \
|
||||
return (*(user)->callback)((user)->data, (const char*)buf, len)
|
||||
|
||||
#include "pack_template.h"
|
||||
|
||||
inline void msgpack_packer_init(msgpack_packer* pk, void* data, msgpack_packer_write callback)
|
||||
{
|
||||
pk->data = data;
|
||||
pk->callback = callback;
|
||||
}
|
||||
|
||||
inline msgpack_packer* msgpack_packer_new(void* data, msgpack_packer_write callback)
|
||||
{
|
||||
msgpack_packer* pk = (msgpack_packer*)calloc(1, sizeof(msgpack_packer));
|
||||
if(!pk) { return NULL; }
|
||||
msgpack_packer_init(pk, data, callback);
|
||||
return pk;
|
||||
}
|
||||
|
||||
inline void msgpack_packer_free(msgpack_packer* pk)
|
||||
{
|
||||
free(pk);
|
||||
}
|
||||
|
||||
inline int msgpack_pack_str_with_body(msgpack_packer* pk, const void* b, size_t l)
|
||||
{
|
||||
int ret = msgpack_pack_str(pk, l);
|
||||
if (ret != 0) { return ret; }
|
||||
return msgpack_pack_str_body(pk, b, l);
|
||||
}
|
||||
|
||||
inline int msgpack_pack_bin_with_body(msgpack_packer* pk, const void* b, size_t l)
|
||||
{
|
||||
int ret = msgpack_pack_bin(pk, l);
|
||||
if (ret != 0) { return ret; }
|
||||
return msgpack_pack_bin_body(pk, b, l);
|
||||
}
|
||||
|
||||
inline int msgpack_pack_ext_with_body(msgpack_packer* pk, const void* b, size_t l, int8_t type)
|
||||
{
|
||||
int ret = msgpack_pack_ext(pk, l, type);
|
||||
if (ret != 0) { return ret; }
|
||||
return msgpack_pack_ext_body(pk, b, l);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/pack.h */
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* MessagePack unpacking routine template
|
||||
*
|
||||
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_PACK_DEFINE_H
|
||||
#define MSGPACK_PACK_DEFINE_H
|
||||
|
||||
#include "sysdep.h"
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#endif /* msgpack/pack_define.h */
|
||||
|
||||
@@ -0,0 +1,952 @@
|
||||
/*
|
||||
* MessagePack packing routine template
|
||||
*
|
||||
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef MSGPACK_ENDIAN_BIG_BYTE
|
||||
#define MSGPACK_ENDIAN_BIG_BYTE 0
|
||||
#endif
|
||||
#ifndef MSGPACK_ENDIAN_LITTLE_BYTE
|
||||
#define MSGPACK_ENDIAN_LITTLE_BYTE 1
|
||||
#endif
|
||||
|
||||
#if MSGPACK_ENDIAN_LITTLE_BYTE
|
||||
#define TAKE8_8(d) ((uint8_t*)&d)[0]
|
||||
#define TAKE8_16(d) ((uint8_t*)&d)[0]
|
||||
#define TAKE8_32(d) ((uint8_t*)&d)[0]
|
||||
#define TAKE8_64(d) ((uint8_t*)&d)[0]
|
||||
#elif MSGPACK_ENDIAN_BIG_BYTE
|
||||
#define TAKE8_8(d) ((uint8_t*)&d)[0]
|
||||
#define TAKE8_16(d) ((uint8_t*)&d)[1]
|
||||
#define TAKE8_32(d) ((uint8_t*)&d)[3]
|
||||
#define TAKE8_64(d) ((uint8_t*)&d)[7]
|
||||
#else
|
||||
#error msgpack-c supports only big endian and little endian
|
||||
#endif
|
||||
|
||||
#ifndef msgpack_pack_inline_func
|
||||
#error msgpack_pack_inline_func template is not defined
|
||||
#endif
|
||||
|
||||
#ifndef msgpack_pack_user
|
||||
#error msgpack_pack_user type is not defined
|
||||
#endif
|
||||
|
||||
#ifndef msgpack_pack_append_buffer
|
||||
#error msgpack_pack_append_buffer callback is not defined
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4204) /* nonstandard extension used: non-constant aggregate initializer */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Integer
|
||||
*/
|
||||
|
||||
#define msgpack_pack_real_uint8(x, d) \
|
||||
do { \
|
||||
if(d < (1<<7)) { \
|
||||
/* fixnum */ \
|
||||
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); \
|
||||
} else { \
|
||||
/* unsigned 8 */ \
|
||||
unsigned char buf[2] = {0xcc, TAKE8_8(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define msgpack_pack_real_uint16(x, d) \
|
||||
do { \
|
||||
if(d < (1<<7)) { \
|
||||
/* fixnum */ \
|
||||
msgpack_pack_append_buffer(x, &TAKE8_16(d), 1); \
|
||||
} else if(d < (1<<8)) { \
|
||||
/* unsigned 8 */ \
|
||||
unsigned char buf[2] = {0xcc, TAKE8_16(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} else { \
|
||||
/* unsigned 16 */ \
|
||||
unsigned char buf[3]; \
|
||||
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 3); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define msgpack_pack_real_uint32(x, d) \
|
||||
do { \
|
||||
if(d < (1<<8)) { \
|
||||
if(d < (1<<7)) { \
|
||||
/* fixnum */ \
|
||||
msgpack_pack_append_buffer(x, &TAKE8_32(d), 1); \
|
||||
} else { \
|
||||
/* unsigned 8 */ \
|
||||
unsigned char buf[2] = {0xcc, TAKE8_32(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} \
|
||||
} else { \
|
||||
if(d < (1<<16)) { \
|
||||
/* unsigned 16 */ \
|
||||
unsigned char buf[3]; \
|
||||
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 3); \
|
||||
} else { \
|
||||
/* unsigned 32 */ \
|
||||
unsigned char buf[5]; \
|
||||
buf[0] = 0xce; _msgpack_store32(&buf[1], (uint32_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 5); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define msgpack_pack_real_uint64(x, d) \
|
||||
do { \
|
||||
if(d < (1ULL<<8)) { \
|
||||
if(d < (1ULL<<7)) { \
|
||||
/* fixnum */ \
|
||||
msgpack_pack_append_buffer(x, &TAKE8_64(d), 1); \
|
||||
} else { \
|
||||
/* unsigned 8 */ \
|
||||
unsigned char buf[2] = {0xcc, TAKE8_64(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} \
|
||||
} else { \
|
||||
if(d < (1ULL<<16)) { \
|
||||
/* unsigned 16 */ \
|
||||
unsigned char buf[3]; \
|
||||
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 3); \
|
||||
} else if(d < (1ULL<<32)) { \
|
||||
/* unsigned 32 */ \
|
||||
unsigned char buf[5]; \
|
||||
buf[0] = 0xce; _msgpack_store32(&buf[1], (uint32_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 5); \
|
||||
} else { \
|
||||
/* unsigned 64 */ \
|
||||
unsigned char buf[9]; \
|
||||
buf[0] = 0xcf; _msgpack_store64(&buf[1], d); \
|
||||
msgpack_pack_append_buffer(x, buf, 9); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define msgpack_pack_real_int8(x, d) \
|
||||
do { \
|
||||
if(d < -(1<<5)) { \
|
||||
/* signed 8 */ \
|
||||
unsigned char buf[2] = {0xd0, TAKE8_8(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} else { \
|
||||
/* fixnum */ \
|
||||
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define msgpack_pack_real_int16(x, d) \
|
||||
do { \
|
||||
if(d < -(1<<5)) { \
|
||||
if(d < -(1<<7)) { \
|
||||
/* signed 16 */ \
|
||||
unsigned char buf[3]; \
|
||||
buf[0] = 0xd1; _msgpack_store16(&buf[1], (int16_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 3); \
|
||||
} else { \
|
||||
/* signed 8 */ \
|
||||
unsigned char buf[2] = {0xd0, TAKE8_16(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} \
|
||||
} else if(d < (1<<7)) { \
|
||||
/* fixnum */ \
|
||||
msgpack_pack_append_buffer(x, &TAKE8_16(d), 1); \
|
||||
} else { \
|
||||
if(d < (1<<8)) { \
|
||||
/* unsigned 8 */ \
|
||||
unsigned char buf[2] = {0xcc, TAKE8_16(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} else { \
|
||||
/* unsigned 16 */ \
|
||||
unsigned char buf[3]; \
|
||||
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 3); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define msgpack_pack_real_int32(x, d) \
|
||||
do { \
|
||||
if(d < -(1<<5)) { \
|
||||
if(d < -(1<<15)) { \
|
||||
/* signed 32 */ \
|
||||
unsigned char buf[5]; \
|
||||
buf[0] = 0xd2; _msgpack_store32(&buf[1], (int32_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 5); \
|
||||
} else if(d < -(1<<7)) { \
|
||||
/* signed 16 */ \
|
||||
unsigned char buf[3]; \
|
||||
buf[0] = 0xd1; _msgpack_store16(&buf[1], (int16_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 3); \
|
||||
} else { \
|
||||
/* signed 8 */ \
|
||||
unsigned char buf[2] = {0xd0, TAKE8_32(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} \
|
||||
} else if(d < (1<<7)) { \
|
||||
/* fixnum */ \
|
||||
msgpack_pack_append_buffer(x, &TAKE8_32(d), 1); \
|
||||
} else { \
|
||||
if(d < (1<<8)) { \
|
||||
/* unsigned 8 */ \
|
||||
unsigned char buf[2] = {0xcc, TAKE8_32(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} else if(d < (1<<16)) { \
|
||||
/* unsigned 16 */ \
|
||||
unsigned char buf[3]; \
|
||||
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 3); \
|
||||
} else { \
|
||||
/* unsigned 32 */ \
|
||||
unsigned char buf[5]; \
|
||||
buf[0] = 0xce; _msgpack_store32(&buf[1], (uint32_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 5); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define msgpack_pack_real_int64(x, d) \
|
||||
do { \
|
||||
if(d < -(1LL<<5)) { \
|
||||
if(d < -(1LL<<15)) { \
|
||||
if(d < -(1LL<<31)) { \
|
||||
/* signed 64 */ \
|
||||
unsigned char buf[9]; \
|
||||
buf[0] = 0xd3; _msgpack_store64(&buf[1], d); \
|
||||
msgpack_pack_append_buffer(x, buf, 9); \
|
||||
} else { \
|
||||
/* signed 32 */ \
|
||||
unsigned char buf[5]; \
|
||||
buf[0] = 0xd2; _msgpack_store32(&buf[1], (int32_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 5); \
|
||||
} \
|
||||
} else { \
|
||||
if(d < -(1<<7)) { \
|
||||
/* signed 16 */ \
|
||||
unsigned char buf[3]; \
|
||||
buf[0] = 0xd1; _msgpack_store16(&buf[1], (int16_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 3); \
|
||||
} else { \
|
||||
/* signed 8 */ \
|
||||
unsigned char buf[2] = {0xd0, TAKE8_64(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} \
|
||||
} \
|
||||
} else if(d < (1<<7)) { \
|
||||
/* fixnum */ \
|
||||
msgpack_pack_append_buffer(x, &TAKE8_64(d), 1); \
|
||||
} else { \
|
||||
if(d < (1LL<<16)) { \
|
||||
if(d < (1<<8)) { \
|
||||
/* unsigned 8 */ \
|
||||
unsigned char buf[2] = {0xcc, TAKE8_64(d)}; \
|
||||
msgpack_pack_append_buffer(x, buf, 2); \
|
||||
} else { \
|
||||
/* unsigned 16 */ \
|
||||
unsigned char buf[3]; \
|
||||
buf[0] = 0xcd; _msgpack_store16(&buf[1], (uint16_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 3); \
|
||||
} \
|
||||
} else { \
|
||||
if(d < (1LL<<32)) { \
|
||||
/* unsigned 32 */ \
|
||||
unsigned char buf[5]; \
|
||||
buf[0] = 0xce; _msgpack_store32(&buf[1], (uint32_t)d); \
|
||||
msgpack_pack_append_buffer(x, buf, 5); \
|
||||
} else { \
|
||||
/* unsigned 64 */ \
|
||||
unsigned char buf[9]; \
|
||||
buf[0] = 0xcf; _msgpack_store64(&buf[1], d); \
|
||||
msgpack_pack_append_buffer(x, buf, 9); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
#ifdef msgpack_pack_inline_func_fixint
|
||||
|
||||
msgpack_pack_inline_func_fixint(_uint8)(msgpack_pack_user x, uint8_t d)
|
||||
{
|
||||
unsigned char buf[2] = {0xcc, TAKE8_8(d)};
|
||||
msgpack_pack_append_buffer(x, buf, 2);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_fixint(_uint16)(msgpack_pack_user x, uint16_t d)
|
||||
{
|
||||
unsigned char buf[3];
|
||||
buf[0] = 0xcd; _msgpack_store16(&buf[1], d);
|
||||
msgpack_pack_append_buffer(x, buf, 3);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_fixint(_uint32)(msgpack_pack_user x, uint32_t d)
|
||||
{
|
||||
unsigned char buf[5];
|
||||
buf[0] = 0xce; _msgpack_store32(&buf[1], d);
|
||||
msgpack_pack_append_buffer(x, buf, 5);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_fixint(_uint64)(msgpack_pack_user x, uint64_t d)
|
||||
{
|
||||
unsigned char buf[9];
|
||||
buf[0] = 0xcf; _msgpack_store64(&buf[1], d);
|
||||
msgpack_pack_append_buffer(x, buf, 9);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_fixint(_int8)(msgpack_pack_user x, int8_t d)
|
||||
{
|
||||
unsigned char buf[2] = {0xd0, TAKE8_8(d)};
|
||||
msgpack_pack_append_buffer(x, buf, 2);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_fixint(_int16)(msgpack_pack_user x, int16_t d)
|
||||
{
|
||||
unsigned char buf[3];
|
||||
buf[0] = 0xd1; _msgpack_store16(&buf[1], d);
|
||||
msgpack_pack_append_buffer(x, buf, 3);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_fixint(_int32)(msgpack_pack_user x, int32_t d)
|
||||
{
|
||||
unsigned char buf[5];
|
||||
buf[0] = 0xd2; _msgpack_store32(&buf[1], d);
|
||||
msgpack_pack_append_buffer(x, buf, 5);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_fixint(_int64)(msgpack_pack_user x, int64_t d)
|
||||
{
|
||||
unsigned char buf[9];
|
||||
buf[0] = 0xd3; _msgpack_store64(&buf[1], d);
|
||||
msgpack_pack_append_buffer(x, buf, 9);
|
||||
}
|
||||
|
||||
#undef msgpack_pack_inline_func_fixint
|
||||
#endif
|
||||
|
||||
|
||||
msgpack_pack_inline_func(_uint8)(msgpack_pack_user x, uint8_t d)
|
||||
{
|
||||
msgpack_pack_real_uint8(x, d);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_uint16)(msgpack_pack_user x, uint16_t d)
|
||||
{
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_uint32)(msgpack_pack_user x, uint32_t d)
|
||||
{
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_uint64)(msgpack_pack_user x, uint64_t d)
|
||||
{
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_int8)(msgpack_pack_user x, int8_t d)
|
||||
{
|
||||
msgpack_pack_real_int8(x, d);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_int16)(msgpack_pack_user x, int16_t d)
|
||||
{
|
||||
msgpack_pack_real_int16(x, d);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_int32)(msgpack_pack_user x, int32_t d)
|
||||
{
|
||||
msgpack_pack_real_int32(x, d);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_int64)(msgpack_pack_user x, int64_t d)
|
||||
{
|
||||
msgpack_pack_real_int64(x, d);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_char)(msgpack_pack_user x, char d)
|
||||
{
|
||||
#if defined(CHAR_MIN)
|
||||
#if CHAR_MIN < 0
|
||||
msgpack_pack_real_int8(x, d);
|
||||
#else
|
||||
msgpack_pack_real_uint8(x, d);
|
||||
#endif
|
||||
#else
|
||||
#error CHAR_MIN is not defined
|
||||
#endif
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_signed_char)(msgpack_pack_user x, signed char d)
|
||||
{
|
||||
msgpack_pack_real_int8(x, d);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_unsigned_char)(msgpack_pack_user x, unsigned char d)
|
||||
{
|
||||
msgpack_pack_real_uint8(x, d);
|
||||
}
|
||||
|
||||
#ifdef msgpack_pack_inline_func_cint
|
||||
|
||||
msgpack_pack_inline_func_cint(_short)(msgpack_pack_user x, short d)
|
||||
{
|
||||
#if defined(SIZEOF_SHORT)
|
||||
#if SIZEOF_SHORT == 2
|
||||
msgpack_pack_real_int16(x, d);
|
||||
#elif SIZEOF_SHORT == 4
|
||||
msgpack_pack_real_int32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_int64(x, d);
|
||||
#endif
|
||||
|
||||
#elif defined(SHRT_MAX)
|
||||
#if SHRT_MAX == 0x7fff
|
||||
msgpack_pack_real_int16(x, d);
|
||||
#elif SHRT_MAX == 0x7fffffff
|
||||
msgpack_pack_real_int32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_int64(x, d);
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(sizeof(short) == 2) {
|
||||
msgpack_pack_real_int16(x, d);
|
||||
} else if(sizeof(short) == 4) {
|
||||
msgpack_pack_real_int32(x, d);
|
||||
} else {
|
||||
msgpack_pack_real_int64(x, d);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_cint(_int)(msgpack_pack_user x, int d)
|
||||
{
|
||||
#if defined(SIZEOF_INT)
|
||||
#if SIZEOF_INT == 2
|
||||
msgpack_pack_real_int16(x, d);
|
||||
#elif SIZEOF_INT == 4
|
||||
msgpack_pack_real_int32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_int64(x, d);
|
||||
#endif
|
||||
|
||||
#elif defined(INT_MAX)
|
||||
#if INT_MAX == 0x7fff
|
||||
msgpack_pack_real_int16(x, d);
|
||||
#elif INT_MAX == 0x7fffffff
|
||||
msgpack_pack_real_int32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_int64(x, d);
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(sizeof(int) == 2) {
|
||||
msgpack_pack_real_int16(x, d);
|
||||
} else if(sizeof(int) == 4) {
|
||||
msgpack_pack_real_int32(x, d);
|
||||
} else {
|
||||
msgpack_pack_real_int64(x, d);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_cint(_long)(msgpack_pack_user x, long d)
|
||||
{
|
||||
#if defined(SIZEOF_LONG)
|
||||
#if SIZEOF_LONG == 2
|
||||
msgpack_pack_real_int16(x, d);
|
||||
#elif SIZEOF_LONG == 4
|
||||
msgpack_pack_real_int32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_int64(x, d);
|
||||
#endif
|
||||
|
||||
#elif defined(LONG_MAX)
|
||||
#if LONG_MAX == 0x7fffL
|
||||
msgpack_pack_real_int16(x, d);
|
||||
#elif LONG_MAX == 0x7fffffffL
|
||||
msgpack_pack_real_int32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_int64(x, d);
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(sizeof(long) == 2) {
|
||||
msgpack_pack_real_int16(x, d);
|
||||
} else if(sizeof(long) == 4) {
|
||||
msgpack_pack_real_int32(x, d);
|
||||
} else {
|
||||
msgpack_pack_real_int64(x, d);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_cint(_long_long)(msgpack_pack_user x, long long d)
|
||||
{
|
||||
#if defined(SIZEOF_LONG_LONG)
|
||||
#if SIZEOF_LONG_LONG == 2
|
||||
msgpack_pack_real_int16(x, d);
|
||||
#elif SIZEOF_LONG_LONG == 4
|
||||
msgpack_pack_real_int32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_int64(x, d);
|
||||
#endif
|
||||
|
||||
#elif defined(LLONG_MAX)
|
||||
#if LLONG_MAX == 0x7fffL
|
||||
msgpack_pack_real_int16(x, d);
|
||||
#elif LLONG_MAX == 0x7fffffffL
|
||||
msgpack_pack_real_int32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_int64(x, d);
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(sizeof(long long) == 2) {
|
||||
msgpack_pack_real_int16(x, d);
|
||||
} else if(sizeof(long long) == 4) {
|
||||
msgpack_pack_real_int32(x, d);
|
||||
} else {
|
||||
msgpack_pack_real_int64(x, d);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_cint(_unsigned_short)(msgpack_pack_user x, unsigned short d)
|
||||
{
|
||||
#if defined(SIZEOF_SHORT)
|
||||
#if SIZEOF_SHORT == 2
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
#elif SIZEOF_SHORT == 4
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
#endif
|
||||
|
||||
#elif defined(USHRT_MAX)
|
||||
#if USHRT_MAX == 0xffffU
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
#elif USHRT_MAX == 0xffffffffU
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(sizeof(unsigned short) == 2) {
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
} else if(sizeof(unsigned short) == 4) {
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
} else {
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_cint(_unsigned_int)(msgpack_pack_user x, unsigned int d)
|
||||
{
|
||||
#if defined(SIZEOF_INT)
|
||||
#if SIZEOF_INT == 2
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
#elif SIZEOF_INT == 4
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
#endif
|
||||
|
||||
#elif defined(UINT_MAX)
|
||||
#if UINT_MAX == 0xffffU
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
#elif UINT_MAX == 0xffffffffU
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(sizeof(unsigned int) == 2) {
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
} else if(sizeof(unsigned int) == 4) {
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
} else {
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_cint(_unsigned_long)(msgpack_pack_user x, unsigned long d)
|
||||
{
|
||||
#if defined(SIZEOF_LONG)
|
||||
#if SIZEOF_LONG == 2
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
#elif SIZEOF_LONG == 4
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
#endif
|
||||
|
||||
#elif defined(ULONG_MAX)
|
||||
#if ULONG_MAX == 0xffffUL
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
#elif ULONG_MAX == 0xffffffffUL
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(sizeof(unsigned long) == 2) {
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
} else if(sizeof(unsigned long) == 4) {
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
} else {
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func_cint(_unsigned_long_long)(msgpack_pack_user x, unsigned long long d)
|
||||
{
|
||||
#if defined(SIZEOF_LONG_LONG)
|
||||
#if SIZEOF_LONG_LONG == 2
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
#elif SIZEOF_LONG_LONG == 4
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
#endif
|
||||
|
||||
#elif defined(ULLONG_MAX)
|
||||
#if ULLONG_MAX == 0xffffUL
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
#elif ULLONG_MAX == 0xffffffffUL
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
#else
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(sizeof(unsigned long long) == 2) {
|
||||
msgpack_pack_real_uint16(x, d);
|
||||
} else if(sizeof(unsigned long long) == 4) {
|
||||
msgpack_pack_real_uint32(x, d);
|
||||
} else {
|
||||
msgpack_pack_real_uint64(x, d);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef msgpack_pack_inline_func_cint
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Float
|
||||
*/
|
||||
|
||||
msgpack_pack_inline_func(_float)(msgpack_pack_user x, float d)
|
||||
{
|
||||
unsigned char buf[5];
|
||||
union { float f; uint32_t i; } mem;
|
||||
mem.f = d;
|
||||
buf[0] = 0xca; _msgpack_store32(&buf[1], mem.i);
|
||||
msgpack_pack_append_buffer(x, buf, 5);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_double)(msgpack_pack_user x, double d)
|
||||
{
|
||||
unsigned char buf[9];
|
||||
union { double f; uint64_t i; } mem;
|
||||
mem.f = d;
|
||||
buf[0] = 0xcb;
|
||||
#if defined(TARGET_OS_IPHONE)
|
||||
// ok
|
||||
#elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
|
||||
// https://github.com/msgpack/msgpack-perl/pull/1
|
||||
mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
|
||||
#endif
|
||||
_msgpack_store64(&buf[1], mem.i);
|
||||
msgpack_pack_append_buffer(x, buf, 9);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Nil
|
||||
*/
|
||||
|
||||
msgpack_pack_inline_func(_nil)(msgpack_pack_user x)
|
||||
{
|
||||
static const unsigned char d = 0xc0;
|
||||
msgpack_pack_append_buffer(x, &d, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Boolean
|
||||
*/
|
||||
|
||||
msgpack_pack_inline_func(_true)(msgpack_pack_user x)
|
||||
{
|
||||
static const unsigned char d = 0xc3;
|
||||
msgpack_pack_append_buffer(x, &d, 1);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_false)(msgpack_pack_user x)
|
||||
{
|
||||
static const unsigned char d = 0xc2;
|
||||
msgpack_pack_append_buffer(x, &d, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Array
|
||||
*/
|
||||
|
||||
msgpack_pack_inline_func(_array)(msgpack_pack_user x, size_t n)
|
||||
{
|
||||
if(n < 16) {
|
||||
unsigned char d = 0x90 | (uint8_t)n;
|
||||
msgpack_pack_append_buffer(x, &d, 1);
|
||||
} else if(n < 65536) {
|
||||
unsigned char buf[3];
|
||||
buf[0] = 0xdc; _msgpack_store16(&buf[1], (uint16_t)n);
|
||||
msgpack_pack_append_buffer(x, buf, 3);
|
||||
} else {
|
||||
unsigned char buf[5];
|
||||
buf[0] = 0xdd; _msgpack_store32(&buf[1], (uint32_t)n);
|
||||
msgpack_pack_append_buffer(x, buf, 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Map
|
||||
*/
|
||||
|
||||
msgpack_pack_inline_func(_map)(msgpack_pack_user x, size_t n)
|
||||
{
|
||||
if(n < 16) {
|
||||
unsigned char d = 0x80 | (uint8_t)n;
|
||||
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1);
|
||||
} else if(n < 65536) {
|
||||
unsigned char buf[3];
|
||||
buf[0] = 0xde; _msgpack_store16(&buf[1], (uint16_t)n);
|
||||
msgpack_pack_append_buffer(x, buf, 3);
|
||||
} else {
|
||||
unsigned char buf[5];
|
||||
buf[0] = 0xdf; _msgpack_store32(&buf[1], (uint32_t)n);
|
||||
msgpack_pack_append_buffer(x, buf, 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Str
|
||||
*/
|
||||
|
||||
msgpack_pack_inline_func(_str)(msgpack_pack_user x, size_t l)
|
||||
{
|
||||
if(l < 32) {
|
||||
unsigned char d = 0xa0 | (uint8_t)l;
|
||||
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1);
|
||||
} else if(l < 256) {
|
||||
unsigned char buf[2];
|
||||
buf[0] = 0xd9; buf[1] = (uint8_t)l;
|
||||
msgpack_pack_append_buffer(x, buf, 2);
|
||||
} else if(l < 65536) {
|
||||
unsigned char buf[3];
|
||||
buf[0] = 0xda; _msgpack_store16(&buf[1], (uint16_t)l);
|
||||
msgpack_pack_append_buffer(x, buf, 3);
|
||||
} else {
|
||||
unsigned char buf[5];
|
||||
buf[0] = 0xdb; _msgpack_store32(&buf[1], (uint32_t)l);
|
||||
msgpack_pack_append_buffer(x, buf, 5);
|
||||
}
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_str_body)(msgpack_pack_user x, const void* b, size_t l)
|
||||
{
|
||||
msgpack_pack_append_buffer(x, (const unsigned char*)b, l);
|
||||
}
|
||||
|
||||
/*
|
||||
* Raw (V4)
|
||||
*/
|
||||
|
||||
msgpack_pack_inline_func(_v4raw)(msgpack_pack_user x, size_t l)
|
||||
{
|
||||
if(l < 32) {
|
||||
unsigned char d = 0xa0 | (uint8_t)l;
|
||||
msgpack_pack_append_buffer(x, &TAKE8_8(d), 1);
|
||||
} else if(l < 65536) {
|
||||
unsigned char buf[3];
|
||||
buf[0] = 0xda; _msgpack_store16(&buf[1], (uint16_t)l);
|
||||
msgpack_pack_append_buffer(x, buf, 3);
|
||||
} else {
|
||||
unsigned char buf[5];
|
||||
buf[0] = 0xdb; _msgpack_store32(&buf[1], (uint32_t)l);
|
||||
msgpack_pack_append_buffer(x, buf, 5);
|
||||
}
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_v4raw_body)(msgpack_pack_user x, const void* b, size_t l)
|
||||
{
|
||||
msgpack_pack_append_buffer(x, (const unsigned char*)b, l);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bin
|
||||
*/
|
||||
|
||||
msgpack_pack_inline_func(_bin)(msgpack_pack_user x, size_t l)
|
||||
{
|
||||
if(l < 256) {
|
||||
unsigned char buf[2];
|
||||
buf[0] = 0xc4; buf[1] = (uint8_t)l;
|
||||
msgpack_pack_append_buffer(x, buf, 2);
|
||||
} else if(l < 65536) {
|
||||
unsigned char buf[3];
|
||||
buf[0] = 0xc5; _msgpack_store16(&buf[1], (uint16_t)l);
|
||||
msgpack_pack_append_buffer(x, buf, 3);
|
||||
} else {
|
||||
unsigned char buf[5];
|
||||
buf[0] = 0xc6; _msgpack_store32(&buf[1], (uint32_t)l);
|
||||
msgpack_pack_append_buffer(x, buf, 5);
|
||||
}
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_bin_body)(msgpack_pack_user x, const void* b, size_t l)
|
||||
{
|
||||
msgpack_pack_append_buffer(x, (const unsigned char*)b, l);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ext
|
||||
*/
|
||||
|
||||
msgpack_pack_inline_func(_ext)(msgpack_pack_user x, size_t l, int8_t type)
|
||||
{
|
||||
switch(l) {
|
||||
case 1: {
|
||||
unsigned char buf[2];
|
||||
buf[0] = 0xd4;
|
||||
buf[1] = (unsigned char)type;
|
||||
msgpack_pack_append_buffer(x, buf, 2);
|
||||
} break;
|
||||
case 2: {
|
||||
unsigned char buf[2];
|
||||
buf[0] = 0xd5;
|
||||
buf[1] = (unsigned char)type;
|
||||
msgpack_pack_append_buffer(x, buf, 2);
|
||||
} break;
|
||||
case 4: {
|
||||
unsigned char buf[2];
|
||||
buf[0] = 0xd6;
|
||||
buf[1] = (unsigned char)type;
|
||||
msgpack_pack_append_buffer(x, buf, 2);
|
||||
} break;
|
||||
case 8: {
|
||||
unsigned char buf[2];
|
||||
buf[0] = 0xd7;
|
||||
buf[1] = (unsigned char)type;
|
||||
msgpack_pack_append_buffer(x, buf, 2);
|
||||
} break;
|
||||
case 16: {
|
||||
unsigned char buf[2];
|
||||
buf[0] = 0xd8;
|
||||
buf[1] = (unsigned char)type;
|
||||
msgpack_pack_append_buffer(x, buf, 2);
|
||||
} break;
|
||||
default:
|
||||
if(l < 256) {
|
||||
unsigned char buf[3];
|
||||
buf[0] = 0xc7;
|
||||
buf[1] = (unsigned char)l;
|
||||
buf[2] = (unsigned char)type;
|
||||
msgpack_pack_append_buffer(x, buf, 3);
|
||||
} else if(l < 65536) {
|
||||
unsigned char buf[4];
|
||||
buf[0] = 0xc8;
|
||||
_msgpack_store16(&buf[1], l);
|
||||
buf[3] = (unsigned char)type;
|
||||
msgpack_pack_append_buffer(x, buf, 4);
|
||||
} else {
|
||||
unsigned char buf[6];
|
||||
buf[0] = 0xc9;
|
||||
_msgpack_store32(&buf[1], l);
|
||||
buf[5] = (unsigned char)type;
|
||||
msgpack_pack_append_buffer(x, buf, 6);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_ext_body)(msgpack_pack_user x, const void* b, size_t l)
|
||||
{
|
||||
msgpack_pack_append_buffer(x, (const unsigned char*)b, l);
|
||||
}
|
||||
|
||||
msgpack_pack_inline_func(_timestamp)(msgpack_pack_user x, const msgpack_timestamp* d)
|
||||
{
|
||||
if ((((int64_t)d->tv_sec) >> 34) == 0) {
|
||||
uint64_t data64 = ((uint64_t) d->tv_nsec << 34) | (uint64_t)d->tv_sec;
|
||||
if ((data64 & 0xffffffff00000000L) == 0) {
|
||||
// timestamp 32
|
||||
char buf[4];
|
||||
uint32_t data32 = (uint32_t)data64;
|
||||
msgpack_pack_ext(x, 4, -1);
|
||||
_msgpack_store32(buf, data32);
|
||||
msgpack_pack_append_buffer(x, buf, 4);
|
||||
} else {
|
||||
// timestamp 64
|
||||
char buf[8];
|
||||
msgpack_pack_ext(x, 8, -1);
|
||||
_msgpack_store64(buf, data64);
|
||||
msgpack_pack_append_buffer(x, buf, 8);
|
||||
}
|
||||
} else {
|
||||
// timestamp 96
|
||||
char buf[12];
|
||||
_msgpack_store32(&buf[0], d->tv_nsec);
|
||||
_msgpack_store64(&buf[4], d->tv_sec);
|
||||
msgpack_pack_ext(x, 12, -1);
|
||||
msgpack_pack_append_buffer(x, buf, 12);
|
||||
}
|
||||
}
|
||||
|
||||
#undef msgpack_pack_inline_func
|
||||
#undef msgpack_pack_user
|
||||
#undef msgpack_pack_append_buffer
|
||||
|
||||
#undef TAKE8_8
|
||||
#undef TAKE8_16
|
||||
#undef TAKE8_32
|
||||
#undef TAKE8_64
|
||||
|
||||
#undef msgpack_pack_real_uint8
|
||||
#undef msgpack_pack_real_uint16
|
||||
#undef msgpack_pack_real_uint32
|
||||
#undef msgpack_pack_real_uint64
|
||||
#undef msgpack_pack_real_int8
|
||||
#undef msgpack_pack_real_int16
|
||||
#undef msgpack_pack_real_int32
|
||||
#undef msgpack_pack_real_int64
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
115
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/sbuffer.h
Normal file
115
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/sbuffer.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* MessagePack for C simple buffer implementation
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_SBUFFER_H
|
||||
#define MSGPACK_SBUFFER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msgpack_sbuffer Simple buffer
|
||||
* @ingroup msgpack_buffer
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef struct msgpack_sbuffer {
|
||||
size_t size;
|
||||
char* data;
|
||||
size_t alloc;
|
||||
} msgpack_sbuffer;
|
||||
|
||||
static inline void msgpack_sbuffer_init(msgpack_sbuffer* sbuf)
|
||||
{
|
||||
memset(sbuf, 0, sizeof(msgpack_sbuffer));
|
||||
}
|
||||
|
||||
static inline void msgpack_sbuffer_destroy(msgpack_sbuffer* sbuf)
|
||||
{
|
||||
free(sbuf->data);
|
||||
}
|
||||
|
||||
static inline msgpack_sbuffer* msgpack_sbuffer_new(void)
|
||||
{
|
||||
return (msgpack_sbuffer*)calloc(1, sizeof(msgpack_sbuffer));
|
||||
}
|
||||
|
||||
static inline void msgpack_sbuffer_free(msgpack_sbuffer* sbuf)
|
||||
{
|
||||
if(sbuf == NULL) { return; }
|
||||
msgpack_sbuffer_destroy(sbuf);
|
||||
free(sbuf);
|
||||
}
|
||||
|
||||
#ifndef MSGPACK_SBUFFER_INIT_SIZE
|
||||
#define MSGPACK_SBUFFER_INIT_SIZE 8192
|
||||
#endif
|
||||
|
||||
static inline int msgpack_sbuffer_write(void* data, const char* buf, size_t len)
|
||||
{
|
||||
msgpack_sbuffer* sbuf = (msgpack_sbuffer*)data;
|
||||
|
||||
assert(buf || len == 0);
|
||||
if(!buf) return 0;
|
||||
|
||||
if(sbuf->alloc - sbuf->size < len) {
|
||||
void* tmp;
|
||||
size_t nsize = (sbuf->alloc) ?
|
||||
sbuf->alloc * 2 : MSGPACK_SBUFFER_INIT_SIZE;
|
||||
|
||||
while(nsize < sbuf->size + len) {
|
||||
size_t tmp_nsize = nsize * 2;
|
||||
if (tmp_nsize <= nsize) {
|
||||
nsize = sbuf->size + len;
|
||||
break;
|
||||
}
|
||||
nsize = tmp_nsize;
|
||||
}
|
||||
|
||||
tmp = realloc(sbuf->data, nsize);
|
||||
if(!tmp) { return -1; }
|
||||
|
||||
sbuf->data = (char*)tmp;
|
||||
sbuf->alloc = nsize;
|
||||
}
|
||||
|
||||
memcpy(sbuf->data + sbuf->size, buf, len);
|
||||
sbuf->size += len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline char* msgpack_sbuffer_release(msgpack_sbuffer* sbuf)
|
||||
{
|
||||
char* tmp = sbuf->data;
|
||||
sbuf->size = 0;
|
||||
sbuf->data = NULL;
|
||||
sbuf->alloc = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline void msgpack_sbuffer_clear(msgpack_sbuffer* sbuf)
|
||||
{
|
||||
sbuf->size = 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/sbuffer.h */
|
||||
228
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/sysdep.h
Normal file
228
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/sysdep.h
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* MessagePack system dependencies
|
||||
*
|
||||
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_SYSDEP_H
|
||||
#define MSGPACK_SYSDEP_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef MSGPACK_ENDIAN_BIG_BYTE
|
||||
#define MSGPACK_ENDIAN_BIG_BYTE 0
|
||||
#endif
|
||||
#ifndef MSGPACK_ENDIAN_LITTLE_BYTE
|
||||
#define MSGPACK_ENDIAN_LITTLE_BYTE 1
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1800
|
||||
# define snprintf(buf, len, format,...) _snprintf_s(buf, len, _TRUNCATE, format, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
typedef signed __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# if defined(_WIN64)
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
# else
|
||||
typedef signed __int32 intptr_t;
|
||||
typedef unsigned __int32 uintptr_t;
|
||||
# endif
|
||||
#elif defined(_MSC_VER) // && _MSC_VER >= 1600
|
||||
# include <stdint.h>
|
||||
#else
|
||||
# include <stdint.h>
|
||||
# include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#if !defined(MSGPACK_DLLEXPORT)
|
||||
#if defined(_MSC_VER)
|
||||
# define MSGPACK_DLLEXPORT __declspec(dllexport)
|
||||
#else /* _MSC_VER */
|
||||
# define MSGPACK_DLLEXPORT
|
||||
#endif /* _MSC_VER */
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# if defined(_KERNEL_MODE)
|
||||
# define _msgpack_atomic_counter_header <ntddk.h>
|
||||
# else
|
||||
# define _msgpack_atomic_counter_header <windows.h>
|
||||
# if !defined(WIN32_LEAN_AND_MEAN)
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif /* WIN32_LEAN_AND_MEAN */
|
||||
# endif
|
||||
typedef long _msgpack_atomic_counter_t;
|
||||
#if defined(_AMD64_) || defined(_M_X64) || defined(_M_ARM64)
|
||||
# define _msgpack_sync_decr_and_fetch(ptr) _InterlockedDecrement(ptr)
|
||||
# define _msgpack_sync_incr_and_fetch(ptr) _InterlockedIncrement(ptr)
|
||||
#else
|
||||
# define _msgpack_sync_decr_and_fetch(ptr) InterlockedDecrement(ptr)
|
||||
# define _msgpack_sync_incr_and_fetch(ptr) InterlockedIncrement(ptr)
|
||||
#endif
|
||||
#elif defined(__GNUC__) && ((__GNUC__*10 + __GNUC_MINOR__) < 41)
|
||||
|
||||
# if defined(__cplusplus)
|
||||
# define _msgpack_atomic_counter_header "msgpack/gcc_atomic.hpp"
|
||||
# else
|
||||
# define _msgpack_atomic_counter_header "msgpack/gcc_atomic.h"
|
||||
# endif
|
||||
|
||||
#else
|
||||
typedef unsigned int _msgpack_atomic_counter_t;
|
||||
# define _msgpack_sync_decr_and_fetch(ptr) __sync_sub_and_fetch(ptr, 1)
|
||||
# define _msgpack_sync_incr_and_fetch(ptr) __sync_add_and_fetch(ptr, 1)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
# ifdef __cplusplus
|
||||
/* numeric_limits<T>::min,max */
|
||||
# ifdef max
|
||||
# undef max
|
||||
# endif
|
||||
# ifdef min
|
||||
# undef min
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#elif defined(unix) || defined(__unix) || defined(__APPLE__) || defined(__OpenBSD__)
|
||||
|
||||
#include <arpa/inet.h> /* __BYTE_ORDER */
|
||||
# if defined(linux)
|
||||
# include <byteswap.h>
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(MSGPACK_ENDIAN_LITTLE_BYTE) && !defined(MSGPACK_ENDIAN_BIG_BYTE)
|
||||
#include <msgpack/predef/other/endian.h>
|
||||
#endif // !defined(MSGPACK_ENDIAN_LITTLE_BYTE) && !defined(MSGPACK_ENDIAN_BIG_BYTE)
|
||||
|
||||
#if MSGPACK_ENDIAN_LITTLE_BYTE
|
||||
|
||||
# if defined(unix) || defined(__unix) || defined(__APPLE__) || defined(__OpenBSD__)
|
||||
# define _msgpack_be16(x) ntohs((uint16_t)x)
|
||||
# else
|
||||
# if defined(ntohs)
|
||||
# define _msgpack_be16(x) ntohs(x)
|
||||
# elif defined(_byteswap_ushort) || (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
# define _msgpack_be16(x) ((uint16_t)_byteswap_ushort((unsigned short)x))
|
||||
# else
|
||||
# define _msgpack_be16(x) ( \
|
||||
((((uint16_t)x) << 8) ) | \
|
||||
((((uint16_t)x) >> 8) ) )
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(unix) || defined(__unix) || defined(__APPLE__) || defined(__OpenBSD__)
|
||||
# define _msgpack_be32(x) ntohl((uint32_t)x)
|
||||
# else
|
||||
# if defined(ntohl)
|
||||
# define _msgpack_be32(x) ntohl(x)
|
||||
# elif defined(_byteswap_ulong) || (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
# define _msgpack_be32(x) ((uint32_t)_byteswap_ulong((unsigned long)x))
|
||||
# else
|
||||
# define _msgpack_be32(x) \
|
||||
( ((((uint32_t)x) << 24) ) | \
|
||||
((((uint32_t)x) << 8) & 0x00ff0000U ) | \
|
||||
((((uint32_t)x) >> 8) & 0x0000ff00U ) | \
|
||||
((((uint32_t)x) >> 24) ) )
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(_byteswap_uint64) || (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
# define _msgpack_be64(x) (_byteswap_uint64(x))
|
||||
# elif defined(bswap_64)
|
||||
# define _msgpack_be64(x) bswap_64(x)
|
||||
# elif defined(__DARWIN_OSSwapInt64)
|
||||
# define _msgpack_be64(x) __DARWIN_OSSwapInt64(x)
|
||||
# else
|
||||
# define _msgpack_be64(x) \
|
||||
( ((((uint64_t)x) << 56) ) | \
|
||||
((((uint64_t)x) << 40) & 0x00ff000000000000ULL ) | \
|
||||
((((uint64_t)x) << 24) & 0x0000ff0000000000ULL ) | \
|
||||
((((uint64_t)x) << 8) & 0x000000ff00000000ULL ) | \
|
||||
((((uint64_t)x) >> 8) & 0x00000000ff000000ULL ) | \
|
||||
((((uint64_t)x) >> 24) & 0x0000000000ff0000ULL ) | \
|
||||
((((uint64_t)x) >> 40) & 0x000000000000ff00ULL ) | \
|
||||
((((uint64_t)x) >> 56) ) )
|
||||
# endif
|
||||
|
||||
#elif MSGPACK_ENDIAN_BIG_BYTE
|
||||
|
||||
# define _msgpack_be16(x) (x)
|
||||
# define _msgpack_be32(x) (x)
|
||||
# define _msgpack_be64(x) (x)
|
||||
|
||||
#else
|
||||
# error msgpack-c supports only big endian and little endian
|
||||
#endif /* MSGPACK_ENDIAN_LITTLE_BYTE */
|
||||
|
||||
#define _msgpack_load16(cast, from, to) do { \
|
||||
memcpy((cast*)(to), (from), sizeof(cast)); \
|
||||
*(to) = (cast)_msgpack_be16(*(to)); \
|
||||
} while (0);
|
||||
|
||||
#define _msgpack_load32(cast, from, to) do { \
|
||||
memcpy((cast*)(to), (from), sizeof(cast)); \
|
||||
*(to) = (cast)_msgpack_be32(*(to)); \
|
||||
} while (0);
|
||||
#define _msgpack_load64(cast, from, to) do { \
|
||||
memcpy((cast*)(to), (from), sizeof(cast)); \
|
||||
*(to) = (cast)_msgpack_be64(*(to)); \
|
||||
} while (0);
|
||||
|
||||
#define _msgpack_store16(to, num) \
|
||||
do { uint16_t val = _msgpack_be16(num); memcpy(to, &val, 2); } while(0)
|
||||
#define _msgpack_store32(to, num) \
|
||||
do { uint32_t val = _msgpack_be32(num); memcpy(to, &val, 4); } while(0)
|
||||
#define _msgpack_store64(to, num) \
|
||||
do { uint64_t val = _msgpack_be64(num); memcpy(to, &val, 8); } while(0)
|
||||
|
||||
/*
|
||||
#define _msgpack_load16(cast, from) \
|
||||
({ cast val; memcpy(&val, (char*)from, 2); _msgpack_be16(val); })
|
||||
#define _msgpack_load32(cast, from) \
|
||||
({ cast val; memcpy(&val, (char*)from, 4); _msgpack_be32(val); })
|
||||
#define _msgpack_load64(cast, from) \
|
||||
({ cast val; memcpy(&val, (char*)from, 8); _msgpack_be64(val); })
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(__cplusplus) && defined(_MSC_VER)
|
||||
# if !defined(_KERNEL_MODE)
|
||||
# if !defined(FALSE)
|
||||
# define FALSE (0)
|
||||
# endif
|
||||
# if !defined(TRUE)
|
||||
# define TRUE (!FALSE)
|
||||
# endif
|
||||
# endif
|
||||
# if _MSC_VER >= 1800
|
||||
# include <stdbool.h>
|
||||
# else
|
||||
# define bool int
|
||||
# define true TRUE
|
||||
# define false FALSE
|
||||
# endif
|
||||
# define inline __inline
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/sysdep.h */
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* MessagePack for C TimeStamp
|
||||
*
|
||||
* Copyright (C) 2018 KONDO Takatoshi
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_TIMESTAMP_H
|
||||
#define MSGPACK_TIMESTAMP_H
|
||||
|
||||
#include "object.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct msgpack_timestamp {
|
||||
int64_t tv_sec;
|
||||
uint32_t tv_nsec;
|
||||
} msgpack_timestamp;
|
||||
|
||||
static inline bool msgpack_object_to_timestamp(const msgpack_object* obj, msgpack_timestamp* ts) {
|
||||
if (obj->type != MSGPACK_OBJECT_EXT) return false;
|
||||
if (obj->via.ext.type != -1) return false;
|
||||
switch (obj->via.ext.size) {
|
||||
case 4:
|
||||
ts->tv_nsec = 0;
|
||||
{
|
||||
uint32_t v;
|
||||
_msgpack_load32(uint32_t, obj->via.ext.ptr, &v);
|
||||
ts->tv_sec = v;
|
||||
}
|
||||
return true;
|
||||
case 8: {
|
||||
uint64_t value;
|
||||
_msgpack_load64(uint64_t, obj->via.ext.ptr, &value);
|
||||
ts->tv_nsec = (uint32_t)(value >> 34);
|
||||
ts->tv_sec = value & 0x00000003ffffffffLL;
|
||||
return true;
|
||||
}
|
||||
case 12:
|
||||
_msgpack_load32(uint32_t, obj->via.ext.ptr, &ts->tv_nsec);
|
||||
_msgpack_load64(int64_t, obj->via.ext.ptr + 4, &ts->tv_sec);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/timestamp.h */
|
||||
281
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/unpack.h
Normal file
281
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/unpack.h
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* MessagePack for C unpacking routine
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_UNPACKER_H
|
||||
#define MSGPACK_UNPACKER_H
|
||||
|
||||
#include "zone.h"
|
||||
#include "object.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msgpack_unpack Deserializer
|
||||
* @ingroup msgpack
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef struct msgpack_unpacked {
|
||||
msgpack_zone* zone;
|
||||
msgpack_object data;
|
||||
} msgpack_unpacked;
|
||||
|
||||
typedef enum {
|
||||
MSGPACK_UNPACK_SUCCESS = 2,
|
||||
MSGPACK_UNPACK_EXTRA_BYTES = 1,
|
||||
MSGPACK_UNPACK_CONTINUE = 0,
|
||||
MSGPACK_UNPACK_PARSE_ERROR = -1,
|
||||
MSGPACK_UNPACK_NOMEM_ERROR = -2
|
||||
} msgpack_unpack_return;
|
||||
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
msgpack_unpack_return
|
||||
msgpack_unpack_next(msgpack_unpacked* result,
|
||||
const char* data, size_t len, size_t* off);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msgpack_unpacker Streaming deserializer
|
||||
* @ingroup msgpack
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef struct msgpack_unpacker {
|
||||
char* buffer;
|
||||
size_t used;
|
||||
size_t free;
|
||||
size_t off;
|
||||
size_t parsed;
|
||||
msgpack_zone* z;
|
||||
size_t initial_buffer_size;
|
||||
void* ctx;
|
||||
} msgpack_unpacker;
|
||||
|
||||
|
||||
#ifndef MSGPACK_UNPACKER_INIT_BUFFER_SIZE
|
||||
#define MSGPACK_UNPACKER_INIT_BUFFER_SIZE (64*1024)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initializes a streaming deserializer.
|
||||
* The initialized deserializer must be destroyed by msgpack_unpacker_destroy(msgpack_unpacker*).
|
||||
*/
|
||||
MSGPACK_DLLEXPORT
|
||||
bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size);
|
||||
|
||||
/**
|
||||
* Destroys a streaming deserializer initialized by msgpack_unpacker_init(msgpack_unpacker*, size_t).
|
||||
*/
|
||||
MSGPACK_DLLEXPORT
|
||||
void msgpack_unpacker_destroy(msgpack_unpacker* mpac);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a streaming deserializer.
|
||||
* The created deserializer must be destroyed by msgpack_unpacker_free(msgpack_unpacker*).
|
||||
*/
|
||||
MSGPACK_DLLEXPORT
|
||||
msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size);
|
||||
|
||||
/**
|
||||
* Frees a streaming deserializer created by msgpack_unpacker_new(size_t).
|
||||
*/
|
||||
MSGPACK_DLLEXPORT
|
||||
void msgpack_unpacker_free(msgpack_unpacker* mpac);
|
||||
|
||||
|
||||
#ifndef MSGPACK_UNPACKER_RESERVE_SIZE
|
||||
#define MSGPACK_UNPACKER_RESERVE_SIZE (32*1024)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Reserves free space of the internal buffer.
|
||||
* Use this function to fill the internal buffer with
|
||||
* msgpack_unpacker_buffer(msgpack_unpacker*),
|
||||
* msgpack_unpacker_buffer_capacity(const msgpack_unpacker*) and
|
||||
* msgpack_unpacker_buffer_consumed(msgpack_unpacker*).
|
||||
*/
|
||||
static inline bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size);
|
||||
|
||||
/**
|
||||
* Gets pointer to the free space of the internal buffer.
|
||||
* Use this function to fill the internal buffer with
|
||||
* msgpack_unpacker_reserve_buffer(msgpack_unpacker*, size_t),
|
||||
* msgpack_unpacker_buffer_capacity(const msgpack_unpacker*) and
|
||||
* msgpack_unpacker_buffer_consumed(msgpack_unpacker*).
|
||||
*/
|
||||
static inline char* msgpack_unpacker_buffer(msgpack_unpacker* mpac);
|
||||
|
||||
/**
|
||||
* Gets size of the free space of the internal buffer.
|
||||
* Use this function to fill the internal buffer with
|
||||
* msgpack_unpacker_reserve_buffer(msgpack_unpacker*, size_t),
|
||||
* msgpack_unpacker_buffer(const msgpack_unpacker*) and
|
||||
* msgpack_unpacker_buffer_consumed(msgpack_unpacker*).
|
||||
*/
|
||||
static inline size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac);
|
||||
|
||||
/**
|
||||
* Notifies the deserializer that the internal buffer filled.
|
||||
* Use this function to fill the internal buffer with
|
||||
* msgpack_unpacker_reserve_buffer(msgpack_unpacker*, size_t),
|
||||
* msgpack_unpacker_buffer(msgpack_unpacker*) and
|
||||
* msgpack_unpacker_buffer_capacity(const msgpack_unpacker*).
|
||||
*/
|
||||
static inline void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size);
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes one object.
|
||||
* Returns true if it successes. Otherwise false is returned.
|
||||
* @param pac pointer to an initialized msgpack_unpacked object.
|
||||
*/
|
||||
MSGPACK_DLLEXPORT
|
||||
msgpack_unpack_return msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* pac);
|
||||
|
||||
/**
|
||||
* Deserializes one object and set the number of parsed bytes involved.
|
||||
* Returns true if it successes. Otherwise false is returned.
|
||||
* @param mpac pointer to an initialized msgpack_unpacker object.
|
||||
* @param result pointer to an initialized msgpack_unpacked object.
|
||||
* @param p_bytes pointer to variable that will be set with the number of parsed bytes.
|
||||
*/
|
||||
MSGPACK_DLLEXPORT
|
||||
msgpack_unpack_return msgpack_unpacker_next_with_size(msgpack_unpacker* mpac,
|
||||
msgpack_unpacked* result,
|
||||
size_t *p_bytes);
|
||||
|
||||
/**
|
||||
* Initializes a msgpack_unpacked object.
|
||||
* The initialized object must be destroyed by msgpack_unpacked_destroy(msgpack_unpacker*).
|
||||
* Use the object with msgpack_unpacker_next(msgpack_unpacker*, msgpack_unpacked*) or
|
||||
* msgpack_unpack_next(msgpack_unpacked*, const char*, size_t, size_t*).
|
||||
*/
|
||||
static inline void msgpack_unpacked_init(msgpack_unpacked* result);
|
||||
|
||||
/**
|
||||
* Destroys a streaming deserializer initialized by msgpack_unpacked().
|
||||
*/
|
||||
static inline void msgpack_unpacked_destroy(msgpack_unpacked* result);
|
||||
|
||||
/**
|
||||
* Releases the memory zone from msgpack_unpacked object.
|
||||
* The released zone must be freed by msgpack_zone_free(msgpack_zone*).
|
||||
*/
|
||||
static inline msgpack_zone* msgpack_unpacked_release_zone(msgpack_unpacked* result);
|
||||
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
int msgpack_unpacker_execute(msgpack_unpacker* mpac);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
void msgpack_unpacker_reset(msgpack_unpacker* mpac);
|
||||
|
||||
static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac);
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
// obsolete
|
||||
MSGPACK_DLLEXPORT
|
||||
msgpack_unpack_return
|
||||
msgpack_unpack(const char* data, size_t len, size_t* off,
|
||||
msgpack_zone* result_zone, msgpack_object* result);
|
||||
|
||||
|
||||
|
||||
|
||||
static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size);
|
||||
|
||||
static inline bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size)
|
||||
{
|
||||
if(mpac->free >= size) { return true; }
|
||||
return msgpack_unpacker_expand_buffer(mpac, size);
|
||||
}
|
||||
|
||||
static inline char* msgpack_unpacker_buffer(msgpack_unpacker* mpac)
|
||||
{
|
||||
return mpac->buffer + mpac->used;
|
||||
}
|
||||
|
||||
static inline size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac)
|
||||
{
|
||||
return mpac->free;
|
||||
}
|
||||
|
||||
static inline void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size)
|
||||
{
|
||||
mpac->used += size;
|
||||
mpac->free -= size;
|
||||
}
|
||||
|
||||
static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac)
|
||||
{
|
||||
return mpac->parsed - mpac->off + mpac->used;
|
||||
}
|
||||
|
||||
static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac)
|
||||
{
|
||||
return mpac->parsed;
|
||||
}
|
||||
|
||||
|
||||
static inline void msgpack_unpacked_init(msgpack_unpacked* result)
|
||||
{
|
||||
memset(result, 0, sizeof(msgpack_unpacked));
|
||||
}
|
||||
|
||||
static inline void msgpack_unpacked_destroy(msgpack_unpacked* result)
|
||||
{
|
||||
if(result->zone != NULL) {
|
||||
msgpack_zone_free(result->zone);
|
||||
result->zone = NULL;
|
||||
memset(&result->data, 0, sizeof(msgpack_object));
|
||||
}
|
||||
}
|
||||
|
||||
static inline msgpack_zone* msgpack_unpacked_release_zone(msgpack_unpacked* result)
|
||||
{
|
||||
if(result->zone != NULL) {
|
||||
msgpack_zone* z = result->zone;
|
||||
result->zone = NULL;
|
||||
return z;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/unpack.h */
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* MessagePack unpacking routine template
|
||||
*
|
||||
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_UNPACK_DEFINE_H
|
||||
#define MSGPACK_UNPACK_DEFINE_H
|
||||
|
||||
#include "sysdep.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MSGPACK_EMBED_STACK_SIZE
|
||||
#define MSGPACK_EMBED_STACK_SIZE 32
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
MSGPACK_CS_HEADER = 0x00, // nil
|
||||
|
||||
//MSGPACK_CS_ = 0x01,
|
||||
//MSGPACK_CS_ = 0x02, // false
|
||||
//MSGPACK_CS_ = 0x03, // true
|
||||
|
||||
MSGPACK_CS_BIN_8 = 0x04,
|
||||
MSGPACK_CS_BIN_16 = 0x05,
|
||||
MSGPACK_CS_BIN_32 = 0x06,
|
||||
|
||||
MSGPACK_CS_EXT_8 = 0x07,
|
||||
MSGPACK_CS_EXT_16 = 0x08,
|
||||
MSGPACK_CS_EXT_32 = 0x09,
|
||||
|
||||
MSGPACK_CS_FLOAT = 0x0a,
|
||||
MSGPACK_CS_DOUBLE = 0x0b,
|
||||
MSGPACK_CS_UINT_8 = 0x0c,
|
||||
MSGPACK_CS_UINT_16 = 0x0d,
|
||||
MSGPACK_CS_UINT_32 = 0x0e,
|
||||
MSGPACK_CS_UINT_64 = 0x0f,
|
||||
MSGPACK_CS_INT_8 = 0x10,
|
||||
MSGPACK_CS_INT_16 = 0x11,
|
||||
MSGPACK_CS_INT_32 = 0x12,
|
||||
MSGPACK_CS_INT_64 = 0x13,
|
||||
|
||||
MSGPACK_CS_FIXEXT_1 = 0x14,
|
||||
MSGPACK_CS_FIXEXT_2 = 0x15,
|
||||
MSGPACK_CS_FIXEXT_4 = 0x16,
|
||||
MSGPACK_CS_FIXEXT_8 = 0x17,
|
||||
MSGPACK_CS_FIXEXT_16 = 0x18,
|
||||
|
||||
MSGPACK_CS_STR_8 = 0x19, // str8
|
||||
MSGPACK_CS_STR_16 = 0x1a, // str16
|
||||
MSGPACK_CS_STR_32 = 0x1b, // str32
|
||||
MSGPACK_CS_ARRAY_16 = 0x1c,
|
||||
MSGPACK_CS_ARRAY_32 = 0x1d,
|
||||
MSGPACK_CS_MAP_16 = 0x1e,
|
||||
MSGPACK_CS_MAP_32 = 0x1f,
|
||||
|
||||
//MSGPACK_ACS_BIG_INT_VALUE,
|
||||
//MSGPACK_ACS_BIG_FLOAT_VALUE,
|
||||
MSGPACK_ACS_STR_VALUE,
|
||||
MSGPACK_ACS_BIN_VALUE,
|
||||
MSGPACK_ACS_EXT_VALUE
|
||||
} msgpack_unpack_state;
|
||||
|
||||
|
||||
typedef enum {
|
||||
MSGPACK_CT_ARRAY_ITEM,
|
||||
MSGPACK_CT_MAP_KEY,
|
||||
MSGPACK_CT_MAP_VALUE
|
||||
} msgpack_container_type;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/unpack_define.h */
|
||||
|
||||
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* MessagePack unpacking routine template
|
||||
*
|
||||
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef msgpack_unpack_func
|
||||
#error msgpack_unpack_func template is not defined
|
||||
#endif
|
||||
|
||||
#ifndef msgpack_unpack_callback
|
||||
#error msgpack_unpack_callback template is not defined
|
||||
#endif
|
||||
|
||||
#ifndef msgpack_unpack_struct
|
||||
#error msgpack_unpack_struct template is not defined
|
||||
#endif
|
||||
|
||||
#ifndef msgpack_unpack_struct_decl
|
||||
#define msgpack_unpack_struct_decl(name) msgpack_unpack_struct(name)
|
||||
#endif
|
||||
|
||||
#ifndef msgpack_unpack_object
|
||||
#error msgpack_unpack_object type is not defined
|
||||
#endif
|
||||
|
||||
#ifndef msgpack_unpack_user
|
||||
#error msgpack_unpack_user type is not defined
|
||||
#endif
|
||||
|
||||
#ifndef USE_CASE_RANGE
|
||||
#if !defined(_MSC_VER)
|
||||
#define USE_CASE_RANGE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_KERNEL_MODE)
|
||||
#undef assert
|
||||
#define assert NT_ASSERT
|
||||
#endif
|
||||
|
||||
msgpack_unpack_struct_decl(_stack) {
|
||||
msgpack_unpack_object obj;
|
||||
size_t count;
|
||||
unsigned int ct;
|
||||
msgpack_unpack_object map_key;
|
||||
};
|
||||
|
||||
msgpack_unpack_struct_decl(_context) {
|
||||
msgpack_unpack_user user;
|
||||
unsigned int cs;
|
||||
unsigned int trail;
|
||||
unsigned int top;
|
||||
/*
|
||||
msgpack_unpack_struct(_stack)* stack;
|
||||
unsigned int stack_size;
|
||||
msgpack_unpack_struct(_stack) embed_stack[MSGPACK_EMBED_STACK_SIZE];
|
||||
*/
|
||||
msgpack_unpack_struct(_stack) stack[MSGPACK_EMBED_STACK_SIZE];
|
||||
};
|
||||
|
||||
|
||||
msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx)
|
||||
{
|
||||
ctx->cs = MSGPACK_CS_HEADER;
|
||||
ctx->trail = 0;
|
||||
ctx->top = 0;
|
||||
/*
|
||||
ctx->stack = ctx->embed_stack;
|
||||
ctx->stack_size = MSGPACK_EMBED_STACK_SIZE;
|
||||
*/
|
||||
ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user);
|
||||
}
|
||||
|
||||
/*
|
||||
msgpack_unpack_func(void, _destroy)(msgpack_unpack_struct(_context)* ctx)
|
||||
{
|
||||
if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) {
|
||||
free(ctx->stack);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx)
|
||||
{
|
||||
return (ctx)->stack[0].obj;
|
||||
}
|
||||
|
||||
|
||||
msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off)
|
||||
{
|
||||
assert(len >= *off);
|
||||
{
|
||||
const unsigned char* p = (unsigned char*)data + *off;
|
||||
const unsigned char* const pe = (unsigned char*)data + len;
|
||||
const void* n = NULL;
|
||||
|
||||
unsigned int trail = ctx->trail;
|
||||
unsigned int cs = ctx->cs;
|
||||
unsigned int top = ctx->top;
|
||||
msgpack_unpack_struct(_stack)* stack = ctx->stack;
|
||||
/*
|
||||
unsigned int stack_size = ctx->stack_size;
|
||||
*/
|
||||
msgpack_unpack_user* user = &ctx->user;
|
||||
|
||||
msgpack_unpack_object obj;
|
||||
msgpack_unpack_struct(_stack)* c = NULL;
|
||||
|
||||
int ret;
|
||||
|
||||
#define push_simple_value(func) \
|
||||
ret = msgpack_unpack_callback(func)(user, &obj); \
|
||||
if(ret < 0) { goto _failed; } \
|
||||
goto _push
|
||||
#define push_fixed_value(func, arg) \
|
||||
ret = msgpack_unpack_callback(func)(user, arg, &obj); \
|
||||
if(ret < 0) { goto _failed; } \
|
||||
goto _push
|
||||
#define push_variable_value(func, base, pos, len) \
|
||||
ret = msgpack_unpack_callback(func)(user, \
|
||||
(const char*)base, (const char*)pos, len, &obj); \
|
||||
if(ret < 0) { goto _failed; } \
|
||||
goto _push
|
||||
|
||||
#define again_fixed_trail(_cs, trail_len) \
|
||||
trail = trail_len; \
|
||||
cs = _cs; \
|
||||
goto _fixed_trail_again
|
||||
#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \
|
||||
trail = trail_len; \
|
||||
if(trail == 0) { goto ifzero; } \
|
||||
cs = _cs; \
|
||||
goto _fixed_trail_again
|
||||
|
||||
#define start_container(func, count_, ct_) \
|
||||
if(top >= MSGPACK_EMBED_STACK_SIZE) { \
|
||||
ret = MSGPACK_UNPACK_NOMEM_ERROR; \
|
||||
goto _failed; \
|
||||
} /* FIXME */ \
|
||||
ret = msgpack_unpack_callback(func)(user, count_, &stack[top].obj); \
|
||||
if(ret < 0) { goto _failed; } \
|
||||
if((count_) == 0) { obj = stack[top].obj; goto _push; } \
|
||||
stack[top].ct = ct_; \
|
||||
stack[top].count = count_; \
|
||||
++top; \
|
||||
goto _header_again
|
||||
|
||||
#define NEXT_CS(p) \
|
||||
((unsigned int)*p & 0x1f)
|
||||
|
||||
#ifdef USE_CASE_RANGE
|
||||
#define SWITCH_RANGE_BEGIN switch(*p) {
|
||||
#define SWITCH_RANGE(FROM, TO) case FROM ... TO:
|
||||
#define SWITCH_RANGE_DEFAULT default:
|
||||
#define SWITCH_RANGE_END }
|
||||
#else
|
||||
#define SWITCH_RANGE_BEGIN { if(0) {
|
||||
#define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) {
|
||||
#define SWITCH_RANGE_DEFAULT } else {
|
||||
#define SWITCH_RANGE_END } }
|
||||
#endif
|
||||
|
||||
if(p == pe) { goto _out; }
|
||||
do {
|
||||
switch(cs) {
|
||||
case MSGPACK_CS_HEADER:
|
||||
SWITCH_RANGE_BEGIN
|
||||
SWITCH_RANGE(0x00, 0x7f) // Positive Fixnum
|
||||
push_fixed_value(_uint8, *(uint8_t*)p);
|
||||
SWITCH_RANGE(0xe0, 0xff) // Negative Fixnum
|
||||
push_fixed_value(_int8, *(int8_t*)p);
|
||||
SWITCH_RANGE(0xc0, 0xdf) // Variable
|
||||
switch(*p) {
|
||||
case 0xc0: // nil
|
||||
push_simple_value(_nil);
|
||||
//case 0xc1: // string
|
||||
// again_terminal_trail(NEXT_CS(p), p+1);
|
||||
case 0xc2: // false
|
||||
push_simple_value(_false);
|
||||
case 0xc3: // true
|
||||
push_simple_value(_true);
|
||||
case 0xc4: // bin 8
|
||||
case 0xc5: // bin 16
|
||||
case 0xc6: // bin 32
|
||||
again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
|
||||
case 0xc7: // ext 8
|
||||
case 0xc8: // ext 16
|
||||
case 0xc9: // ext 32
|
||||
again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) + 1) & 0x03));
|
||||
case 0xca: // float
|
||||
case 0xcb: // double
|
||||
case 0xcc: // unsigned int 8
|
||||
case 0xcd: // unsigned int 16
|
||||
case 0xce: // unsigned int 32
|
||||
case 0xcf: // unsigned int 64
|
||||
case 0xd0: // signed int 8
|
||||
case 0xd1: // signed int 16
|
||||
case 0xd2: // signed int 32
|
||||
case 0xd3: // signed int 64
|
||||
again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
|
||||
case 0xd4: // fixext 1
|
||||
case 0xd5: // fixext 2
|
||||
case 0xd6: // fixext 4
|
||||
case 0xd7: // fixext 8
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE,
|
||||
(1 << (((unsigned int)*p) & 0x03)) + 1, _ext_zero);
|
||||
case 0xd8: // fixext 16
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero);
|
||||
|
||||
case 0xd9: // str 8
|
||||
case 0xda: // str 16
|
||||
case 0xdb: // str 32
|
||||
again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) & 0x03) - 1));
|
||||
case 0xdc: // array 16
|
||||
case 0xdd: // array 32
|
||||
case 0xde: // map 16
|
||||
case 0xdf: // map 32
|
||||
again_fixed_trail(NEXT_CS(p), 2u << (((unsigned int)*p) & 0x01));
|
||||
default:
|
||||
ret = MSGPACK_UNPACK_PARSE_ERROR;
|
||||
goto _failed;
|
||||
}
|
||||
SWITCH_RANGE(0xa0, 0xbf) // FixStr
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, ((unsigned int)*p & 0x1f), _str_zero);
|
||||
SWITCH_RANGE(0x90, 0x9f) // FixArray
|
||||
start_container(_array, ((unsigned int)*p) & 0x0f, MSGPACK_CT_ARRAY_ITEM);
|
||||
SWITCH_RANGE(0x80, 0x8f) // FixMap
|
||||
start_container(_map, ((unsigned int)*p) & 0x0f, MSGPACK_CT_MAP_KEY);
|
||||
|
||||
SWITCH_RANGE_DEFAULT
|
||||
ret = MSGPACK_UNPACK_PARSE_ERROR;
|
||||
goto _failed;
|
||||
SWITCH_RANGE_END
|
||||
// end MSGPACK_CS_HEADER
|
||||
|
||||
|
||||
_fixed_trail_again:
|
||||
++p;
|
||||
// fallthrough
|
||||
|
||||
default:
|
||||
if((size_t)(pe - p) < trail) { goto _out; }
|
||||
n = p; p += trail - 1;
|
||||
switch(cs) {
|
||||
//case MSGPACK_CS_
|
||||
//case MSGPACK_CS_
|
||||
case MSGPACK_CS_FLOAT: {
|
||||
union { uint32_t i; float f; } mem;
|
||||
_msgpack_load32(uint32_t, n, &mem.i);
|
||||
push_fixed_value(_float, mem.f); }
|
||||
case MSGPACK_CS_DOUBLE: {
|
||||
union { uint64_t i; double f; } mem;
|
||||
_msgpack_load64(uint64_t, n, &mem.i);
|
||||
#if defined(TARGET_OS_IPHONE)
|
||||
// ok
|
||||
#elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
|
||||
// https://github.com/msgpack/msgpack-perl/pull/1
|
||||
mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
|
||||
#endif
|
||||
push_fixed_value(_double, mem.f); }
|
||||
case MSGPACK_CS_UINT_8:
|
||||
push_fixed_value(_uint8, *(uint8_t*)n);
|
||||
case MSGPACK_CS_UINT_16:{
|
||||
uint16_t tmp;
|
||||
_msgpack_load16(uint16_t,n,&tmp);
|
||||
push_fixed_value(_uint16, tmp);
|
||||
}
|
||||
case MSGPACK_CS_UINT_32:{
|
||||
uint32_t tmp;
|
||||
_msgpack_load32(uint32_t,n,&tmp);
|
||||
push_fixed_value(_uint32, tmp);
|
||||
}
|
||||
case MSGPACK_CS_UINT_64:{
|
||||
uint64_t tmp;
|
||||
_msgpack_load64(uint64_t,n,&tmp);
|
||||
push_fixed_value(_uint64, tmp);
|
||||
}
|
||||
case MSGPACK_CS_INT_8:
|
||||
push_fixed_value(_int8, *(int8_t*)n);
|
||||
case MSGPACK_CS_INT_16:{
|
||||
int16_t tmp;
|
||||
_msgpack_load16(int16_t,n,&tmp);
|
||||
push_fixed_value(_int16, tmp);
|
||||
}
|
||||
case MSGPACK_CS_INT_32:{
|
||||
int32_t tmp;
|
||||
_msgpack_load32(int32_t,n,&tmp);
|
||||
push_fixed_value(_int32, tmp);
|
||||
}
|
||||
case MSGPACK_CS_INT_64:{
|
||||
int64_t tmp;
|
||||
_msgpack_load64(int64_t,n,&tmp);
|
||||
push_fixed_value(_int64, tmp);
|
||||
}
|
||||
case MSGPACK_CS_FIXEXT_1:
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 1+1, _ext_zero);
|
||||
case MSGPACK_CS_FIXEXT_2:
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 2+1, _ext_zero);
|
||||
case MSGPACK_CS_FIXEXT_4:
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 4+1, _ext_zero);
|
||||
case MSGPACK_CS_FIXEXT_8:
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 8+1, _ext_zero);
|
||||
case MSGPACK_CS_FIXEXT_16:
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero);
|
||||
case MSGPACK_CS_STR_8:
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, *(uint8_t*)n, _str_zero);
|
||||
case MSGPACK_CS_BIN_8:
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, *(uint8_t*)n, _bin_zero);
|
||||
case MSGPACK_CS_EXT_8:
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, (*(uint8_t*)n) + 1, _ext_zero);
|
||||
case MSGPACK_CS_STR_16:{
|
||||
uint16_t tmp;
|
||||
_msgpack_load16(uint16_t,n,&tmp);
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero);
|
||||
}
|
||||
case MSGPACK_CS_BIN_16:{
|
||||
uint16_t tmp;
|
||||
_msgpack_load16(uint16_t,n,&tmp);
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero);
|
||||
}
|
||||
case MSGPACK_CS_EXT_16:{
|
||||
uint16_t tmp;
|
||||
_msgpack_load16(uint16_t,n,&tmp);
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero);
|
||||
}
|
||||
case MSGPACK_CS_STR_32:{
|
||||
uint32_t tmp;
|
||||
_msgpack_load32(uint32_t,n,&tmp);
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero);
|
||||
}
|
||||
case MSGPACK_CS_BIN_32:{
|
||||
uint32_t tmp;
|
||||
_msgpack_load32(uint32_t,n,&tmp);
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero);
|
||||
}
|
||||
case MSGPACK_CS_EXT_32:{
|
||||
uint32_t tmp;
|
||||
_msgpack_load32(uint32_t,n,&tmp);
|
||||
again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero);
|
||||
}
|
||||
case MSGPACK_ACS_STR_VALUE:
|
||||
_str_zero:
|
||||
push_variable_value(_str, data, n, trail);
|
||||
case MSGPACK_ACS_BIN_VALUE:
|
||||
_bin_zero:
|
||||
push_variable_value(_bin, data, n, trail);
|
||||
case MSGPACK_ACS_EXT_VALUE:
|
||||
_ext_zero:
|
||||
push_variable_value(_ext, data, n, trail);
|
||||
|
||||
case MSGPACK_CS_ARRAY_16:{
|
||||
uint16_t tmp;
|
||||
_msgpack_load16(uint16_t,n,&tmp);
|
||||
start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM);
|
||||
}
|
||||
case MSGPACK_CS_ARRAY_32:{
|
||||
/* FIXME security guard */
|
||||
uint32_t tmp;
|
||||
_msgpack_load32(uint32_t,n,&tmp);
|
||||
start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM);
|
||||
}
|
||||
|
||||
case MSGPACK_CS_MAP_16:{
|
||||
uint16_t tmp;
|
||||
_msgpack_load16(uint16_t,n,&tmp);
|
||||
start_container(_map, tmp, MSGPACK_CT_MAP_KEY);
|
||||
}
|
||||
case MSGPACK_CS_MAP_32:{
|
||||
/* FIXME security guard */
|
||||
uint32_t tmp;
|
||||
_msgpack_load32(uint32_t,n,&tmp);
|
||||
start_container(_map, tmp, MSGPACK_CT_MAP_KEY);
|
||||
}
|
||||
|
||||
default:
|
||||
ret = MSGPACK_UNPACK_PARSE_ERROR;
|
||||
goto _failed;
|
||||
}
|
||||
}
|
||||
|
||||
_push:
|
||||
if(top == 0) { goto _finish; }
|
||||
c = &stack[top-1];
|
||||
switch(c->ct) {
|
||||
case MSGPACK_CT_ARRAY_ITEM:
|
||||
ret = msgpack_unpack_callback(_array_item)(user, &c->obj, obj); \
|
||||
if(ret < 0) { goto _failed; }
|
||||
if(--c->count == 0) {
|
||||
obj = c->obj;
|
||||
--top;
|
||||
/*printf("stack pop %d\n", top);*/
|
||||
goto _push;
|
||||
}
|
||||
goto _header_again;
|
||||
case MSGPACK_CT_MAP_KEY:
|
||||
c->map_key = obj;
|
||||
c->ct = MSGPACK_CT_MAP_VALUE;
|
||||
goto _header_again;
|
||||
case MSGPACK_CT_MAP_VALUE:
|
||||
ret = msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj); \
|
||||
if(ret < 0) { goto _failed; }
|
||||
if(--c->count == 0) {
|
||||
obj = c->obj;
|
||||
--top;
|
||||
/*printf("stack pop %d\n", top);*/
|
||||
goto _push;
|
||||
}
|
||||
c->ct = MSGPACK_CT_MAP_KEY;
|
||||
goto _header_again;
|
||||
|
||||
default:
|
||||
ret = MSGPACK_UNPACK_PARSE_ERROR;
|
||||
goto _failed;
|
||||
}
|
||||
|
||||
_header_again:
|
||||
cs = MSGPACK_CS_HEADER;
|
||||
++p;
|
||||
} while(p != pe);
|
||||
goto _out;
|
||||
|
||||
|
||||
_finish:
|
||||
stack[0].obj = obj;
|
||||
++p;
|
||||
ret = 1;
|
||||
/*printf("-- finish --\n"); */
|
||||
goto _end;
|
||||
|
||||
_failed:
|
||||
/*printf("** FAILED **\n"); */
|
||||
goto _end;
|
||||
|
||||
_out:
|
||||
ret = 0;
|
||||
goto _end;
|
||||
|
||||
_end:
|
||||
ctx->cs = cs;
|
||||
ctx->trail = trail;
|
||||
ctx->top = top;
|
||||
*off = (size_t)(p - (const unsigned char*)data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#undef msgpack_unpack_func
|
||||
#undef msgpack_unpack_callback
|
||||
#undef msgpack_unpack_struct
|
||||
#undef msgpack_unpack_object
|
||||
#undef msgpack_unpack_user
|
||||
|
||||
#undef push_simple_value
|
||||
#undef push_fixed_value
|
||||
#undef push_variable_value
|
||||
#undef again_fixed_trail
|
||||
#undef again_fixed_trail_if_zero
|
||||
#undef start_container
|
||||
|
||||
#undef NEXT_CS
|
||||
|
||||
#undef SWITCH_RANGE_BEGIN
|
||||
#undef SWITCH_RANGE
|
||||
#undef SWITCH_RANGE_DEFAULT
|
||||
#undef SWITCH_RANGE_END
|
||||
15
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/util.h
Normal file
15
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/util.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* MessagePack for C utilities
|
||||
*
|
||||
* Copyright (C) 2014 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_UTIL_H
|
||||
#define MSGPACK_UTIL_H
|
||||
|
||||
#define MSGPACK_UNUSED(a) (void)(a)
|
||||
|
||||
#endif /* MSGPACK_UTIL_H */
|
||||
@@ -0,0 +1,3 @@
|
||||
#define MSGPACK_VERSION_MAJOR 4
|
||||
#define MSGPACK_VERSION_MINOR 0
|
||||
#define MSGPACK_VERSION_REVISION 0
|
||||
146
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/vrefbuffer.h
Normal file
146
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/vrefbuffer.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* MessagePack for C zero-copy buffer implementation
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_VREFBUFFER_H
|
||||
#define MSGPACK_VREFBUFFER_H
|
||||
|
||||
#include "zone.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(unix) || defined(__unix) || defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__QNX__) || defined(__QNXTO__) || defined(__HAIKU__)
|
||||
#include <sys/uio.h>
|
||||
typedef struct iovec msgpack_iovec;
|
||||
#else
|
||||
struct msgpack_iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
typedef struct msgpack_iovec msgpack_iovec;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msgpack_vrefbuffer Vectored Referencing buffer
|
||||
* @ingroup msgpack_buffer
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct msgpack_vrefbuffer_chunk;
|
||||
typedef struct msgpack_vrefbuffer_chunk msgpack_vrefbuffer_chunk;
|
||||
|
||||
typedef struct msgpack_vrefbuffer_inner_buffer {
|
||||
size_t free;
|
||||
char* ptr;
|
||||
msgpack_vrefbuffer_chunk* head;
|
||||
} msgpack_vrefbuffer_inner_buffer;
|
||||
|
||||
typedef struct msgpack_vrefbuffer {
|
||||
msgpack_iovec* tail;
|
||||
msgpack_iovec* end;
|
||||
msgpack_iovec* array;
|
||||
|
||||
size_t chunk_size;
|
||||
size_t ref_size;
|
||||
|
||||
msgpack_vrefbuffer_inner_buffer inner_buffer;
|
||||
} msgpack_vrefbuffer;
|
||||
|
||||
|
||||
#ifndef MSGPACK_VREFBUFFER_REF_SIZE
|
||||
#define MSGPACK_VREFBUFFER_REF_SIZE 32
|
||||
#endif
|
||||
|
||||
#ifndef MSGPACK_VREFBUFFER_CHUNK_SIZE
|
||||
#define MSGPACK_VREFBUFFER_CHUNK_SIZE 8192
|
||||
#endif
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
|
||||
size_t ref_size, size_t chunk_size);
|
||||
MSGPACK_DLLEXPORT
|
||||
void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf);
|
||||
|
||||
static inline msgpack_vrefbuffer* msgpack_vrefbuffer_new(size_t ref_size, size_t chunk_size);
|
||||
static inline void msgpack_vrefbuffer_free(msgpack_vrefbuffer* vbuf);
|
||||
|
||||
static inline int msgpack_vrefbuffer_write(void* data, const char* buf, size_t len);
|
||||
|
||||
static inline const msgpack_iovec* msgpack_vrefbuffer_vec(const msgpack_vrefbuffer* vref);
|
||||
static inline size_t msgpack_vrefbuffer_veclen(const msgpack_vrefbuffer* vref);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
|
||||
const char* buf, size_t len);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
|
||||
const char* buf, size_t len);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vref);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
static inline msgpack_vrefbuffer* msgpack_vrefbuffer_new(size_t ref_size, size_t chunk_size)
|
||||
{
|
||||
msgpack_vrefbuffer* vbuf = (msgpack_vrefbuffer*)malloc(sizeof(msgpack_vrefbuffer));
|
||||
if (vbuf == NULL) return NULL;
|
||||
if(!msgpack_vrefbuffer_init(vbuf, ref_size, chunk_size)) {
|
||||
free(vbuf);
|
||||
return NULL;
|
||||
}
|
||||
return vbuf;
|
||||
}
|
||||
|
||||
static inline void msgpack_vrefbuffer_free(msgpack_vrefbuffer* vbuf)
|
||||
{
|
||||
if(vbuf == NULL) { return; }
|
||||
msgpack_vrefbuffer_destroy(vbuf);
|
||||
free(vbuf);
|
||||
}
|
||||
|
||||
static inline int msgpack_vrefbuffer_write(void* data, const char* buf, size_t len)
|
||||
{
|
||||
msgpack_vrefbuffer* vbuf = (msgpack_vrefbuffer*)data;
|
||||
assert(buf || len == 0);
|
||||
|
||||
if(!buf) return 0;
|
||||
|
||||
if(len < vbuf->ref_size) {
|
||||
return msgpack_vrefbuffer_append_copy(vbuf, buf, len);
|
||||
} else {
|
||||
return msgpack_vrefbuffer_append_ref(vbuf, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline const msgpack_iovec* msgpack_vrefbuffer_vec(const msgpack_vrefbuffer* vref)
|
||||
{
|
||||
return vref->array;
|
||||
}
|
||||
|
||||
static inline size_t msgpack_vrefbuffer_veclen(const msgpack_vrefbuffer* vref)
|
||||
{
|
||||
return (size_t)(vref->tail - vref->array);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/vrefbuffer.h */
|
||||
205
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/zbuffer.h
Normal file
205
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/zbuffer.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* MessagePack for C deflate buffer implementation
|
||||
*
|
||||
* Copyright (C) 2010 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_ZBUFFER_H
|
||||
#define MSGPACK_ZBUFFER_H
|
||||
|
||||
#include "sysdep.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msgpack_zbuffer Compressed buffer
|
||||
* @ingroup msgpack_buffer
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef struct msgpack_zbuffer {
|
||||
z_stream stream;
|
||||
char* data;
|
||||
size_t init_size;
|
||||
} msgpack_zbuffer;
|
||||
|
||||
#ifndef MSGPACK_ZBUFFER_INIT_SIZE
|
||||
#define MSGPACK_ZBUFFER_INIT_SIZE 8192
|
||||
#endif
|
||||
|
||||
static inline bool msgpack_zbuffer_init(
|
||||
msgpack_zbuffer* zbuf, int level, size_t init_size);
|
||||
static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf);
|
||||
|
||||
static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size);
|
||||
static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf);
|
||||
|
||||
static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf);
|
||||
|
||||
static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf);
|
||||
static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf);
|
||||
|
||||
static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf);
|
||||
static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf);
|
||||
static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf);
|
||||
|
||||
|
||||
#ifndef MSGPACK_ZBUFFER_RESERVE_SIZE
|
||||
#define MSGPACK_ZBUFFER_RESERVE_SIZE 512
|
||||
#endif
|
||||
|
||||
static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len);
|
||||
|
||||
static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf);
|
||||
|
||||
|
||||
static inline bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf,
|
||||
int level, size_t init_size)
|
||||
{
|
||||
memset(zbuf, 0, sizeof(msgpack_zbuffer));
|
||||
zbuf->init_size = init_size;
|
||||
if(deflateInit(&zbuf->stream, level) != Z_OK) {
|
||||
free(zbuf->data);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf)
|
||||
{
|
||||
deflateEnd(&zbuf->stream);
|
||||
free(zbuf->data);
|
||||
}
|
||||
|
||||
static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size)
|
||||
{
|
||||
msgpack_zbuffer* zbuf = (msgpack_zbuffer*)malloc(sizeof(msgpack_zbuffer));
|
||||
if (zbuf == NULL) return NULL;
|
||||
if(!msgpack_zbuffer_init(zbuf, level, init_size)) {
|
||||
free(zbuf);
|
||||
return NULL;
|
||||
}
|
||||
return zbuf;
|
||||
}
|
||||
|
||||
static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf)
|
||||
{
|
||||
if(zbuf == NULL) { return; }
|
||||
msgpack_zbuffer_destroy(zbuf);
|
||||
free(zbuf);
|
||||
}
|
||||
|
||||
static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf)
|
||||
{
|
||||
size_t used = (size_t)((char *)(zbuf->stream.next_out) - zbuf->data);
|
||||
size_t csize = used + zbuf->stream.avail_out;
|
||||
|
||||
size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2;
|
||||
|
||||
char* tmp = (char*)realloc(zbuf->data, nsize);
|
||||
if(tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
zbuf->data = tmp;
|
||||
zbuf->stream.next_out = (Bytef*)(tmp + used);
|
||||
zbuf->stream.avail_out = (uInt)(nsize - used);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len)
|
||||
{
|
||||
msgpack_zbuffer* zbuf = (msgpack_zbuffer*)data;
|
||||
|
||||
assert(buf || len == 0);
|
||||
if(!buf) return 0;
|
||||
|
||||
zbuf->stream.next_in = (Bytef*)buf;
|
||||
zbuf->stream.avail_in = (uInt)len;
|
||||
|
||||
while(zbuf->stream.avail_in > 0) {
|
||||
if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
|
||||
if(!msgpack_zbuffer_expand(zbuf)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf)
|
||||
{
|
||||
while(true) {
|
||||
switch(deflate(&zbuf->stream, Z_FINISH)) {
|
||||
case Z_STREAM_END:
|
||||
return zbuf->data;
|
||||
case Z_OK:
|
||||
case Z_BUF_ERROR:
|
||||
if(!msgpack_zbuffer_expand(zbuf)) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf)
|
||||
{
|
||||
return zbuf->data;
|
||||
}
|
||||
|
||||
static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf)
|
||||
{
|
||||
return (size_t)((char *)(zbuf->stream.next_out) - zbuf->data);
|
||||
}
|
||||
|
||||
static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf)
|
||||
{
|
||||
zbuf->stream.avail_out += (uInt)((char*)zbuf->stream.next_out - zbuf->data);
|
||||
zbuf->stream.next_out = (Bytef*)zbuf->data;
|
||||
}
|
||||
|
||||
static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf)
|
||||
{
|
||||
if(deflateReset(&zbuf->stream) != Z_OK) {
|
||||
return false;
|
||||
}
|
||||
msgpack_zbuffer_reset_buffer(zbuf);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf)
|
||||
{
|
||||
char* tmp = zbuf->data;
|
||||
zbuf->data = NULL;
|
||||
zbuf->stream.next_out = NULL;
|
||||
zbuf->stream.avail_out = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/zbuffer.h */
|
||||
163
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/zone.h
Normal file
163
local_pod_repo/msgpack-c/msgpack-c/include/msgpack/zone.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* MessagePack for C memory pool implementation
|
||||
*
|
||||
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef MSGPACK_ZONE_H
|
||||
#define MSGPACK_ZONE_H
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msgpack_zone Memory zone
|
||||
* @ingroup msgpack
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef struct msgpack_zone_finalizer {
|
||||
void (*func)(void* data);
|
||||
void* data;
|
||||
} msgpack_zone_finalizer;
|
||||
|
||||
typedef struct msgpack_zone_finalizer_array {
|
||||
msgpack_zone_finalizer* tail;
|
||||
msgpack_zone_finalizer* end;
|
||||
msgpack_zone_finalizer* array;
|
||||
} msgpack_zone_finalizer_array;
|
||||
|
||||
struct msgpack_zone_chunk;
|
||||
typedef struct msgpack_zone_chunk msgpack_zone_chunk;
|
||||
|
||||
typedef struct msgpack_zone_chunk_list {
|
||||
size_t free;
|
||||
char* ptr;
|
||||
msgpack_zone_chunk* head;
|
||||
} msgpack_zone_chunk_list;
|
||||
|
||||
typedef struct msgpack_zone {
|
||||
msgpack_zone_chunk_list chunk_list;
|
||||
msgpack_zone_finalizer_array finalizer_array;
|
||||
size_t chunk_size;
|
||||
} msgpack_zone;
|
||||
|
||||
#ifndef MSGPACK_ZONE_CHUNK_SIZE
|
||||
#define MSGPACK_ZONE_CHUNK_SIZE 8192
|
||||
#endif
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size);
|
||||
MSGPACK_DLLEXPORT
|
||||
void msgpack_zone_destroy(msgpack_zone* zone);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
msgpack_zone* msgpack_zone_new(size_t chunk_size);
|
||||
MSGPACK_DLLEXPORT
|
||||
void msgpack_zone_free(msgpack_zone* zone);
|
||||
|
||||
static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size);
|
||||
static inline void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size);
|
||||
|
||||
static inline bool msgpack_zone_push_finalizer(msgpack_zone* zone,
|
||||
void (*func)(void* data), void* data);
|
||||
|
||||
static inline void msgpack_zone_swap(msgpack_zone* a, msgpack_zone* b);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
bool msgpack_zone_is_empty(msgpack_zone* zone);
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
void msgpack_zone_clear(msgpack_zone* zone);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifndef MSGPACK_ZONE_ALIGN
|
||||
#define MSGPACK_ZONE_ALIGN sizeof(void*)
|
||||
#endif
|
||||
|
||||
MSGPACK_DLLEXPORT
|
||||
void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size);
|
||||
|
||||
static inline void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size)
|
||||
{
|
||||
char* ptr;
|
||||
msgpack_zone_chunk_list* cl = &zone->chunk_list;
|
||||
|
||||
if(zone->chunk_list.free < size) {
|
||||
return msgpack_zone_malloc_expand(zone, size);
|
||||
}
|
||||
|
||||
ptr = cl->ptr;
|
||||
cl->free -= size;
|
||||
cl->ptr += size;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size)
|
||||
{
|
||||
char* aligned =
|
||||
(char*)(
|
||||
(uintptr_t)(
|
||||
zone->chunk_list.ptr + (MSGPACK_ZONE_ALIGN - 1)
|
||||
) & ~(uintptr_t)(MSGPACK_ZONE_ALIGN - 1)
|
||||
);
|
||||
size_t adjusted_size = size + (size_t)(aligned - zone->chunk_list.ptr);
|
||||
if(zone->chunk_list.free >= adjusted_size) {
|
||||
zone->chunk_list.free -= adjusted_size;
|
||||
zone->chunk_list.ptr += adjusted_size;
|
||||
return aligned;
|
||||
}
|
||||
{
|
||||
void* ptr = msgpack_zone_malloc_expand(zone, size + (MSGPACK_ZONE_ALIGN - 1));
|
||||
if (ptr) {
|
||||
return (char*)((uintptr_t)(ptr) & ~(uintptr_t)(MSGPACK_ZONE_ALIGN - 1));
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone,
|
||||
void (*func)(void* data), void* data);
|
||||
|
||||
static inline bool msgpack_zone_push_finalizer(msgpack_zone* zone,
|
||||
void (*func)(void* data), void* data)
|
||||
{
|
||||
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
|
||||
msgpack_zone_finalizer* fin = fa->tail;
|
||||
|
||||
if(fin == fa->end) {
|
||||
return msgpack_zone_push_finalizer_expand(zone, func, data);
|
||||
}
|
||||
|
||||
fin->func = func;
|
||||
fin->data = data;
|
||||
|
||||
++fa->tail;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void msgpack_zone_swap(msgpack_zone* a, msgpack_zone* b)
|
||||
{
|
||||
msgpack_zone tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/zone.h */
|
||||
19
local_pod_repo/msgpack-c/msgpack-c/msgpack-config.cmake.in
Normal file
19
local_pod_repo/msgpack-c/msgpack-c/msgpack-config.cmake.in
Normal file
@@ -0,0 +1,19 @@
|
||||
#.rst:
|
||||
# msgpack
|
||||
# -------
|
||||
#
|
||||
# The following import targets are created
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# msgpackc
|
||||
# msgpackc-static (optional)
|
||||
#
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
if(NOT TARGET msgpackc AND NOT TARGET msgpackc-static)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/msgpack-targets.cmake")
|
||||
endif()
|
||||
10
local_pod_repo/msgpack-c/msgpack-c/msgpack.pc.in
Normal file
10
local_pod_repo/msgpack-c/msgpack-c/msgpack.pc.in
Normal file
@@ -0,0 +1,10 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: MessagePack
|
||||
Description: Binary-based efficient object serialization library
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lmsgpackc
|
||||
Cflags: -I${includedir}
|
||||
484
local_pod_repo/msgpack-c/msgpack-c/src/objectc.c
Normal file
484
local_pod_repo/msgpack-c/msgpack-c/src/objectc.c
Normal file
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* MessagePack for C dynamic typing routine
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#if defined(_KERNEL_MODE)
|
||||
# undef _NO_CRT_STDIO_INLINE
|
||||
# define _NO_CRT_STDIO_INLINE
|
||||
#endif
|
||||
|
||||
#include "object.h"
|
||||
#include "pack.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if _MSC_VER >= 1800
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
#define PRIu64 "I64u"
|
||||
#define PRIi64 "I64i"
|
||||
#define PRIi8 "i"
|
||||
#endif
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#if defined(_KERNEL_MODE)
|
||||
# undef snprintf
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
int msgpack_pack_object(msgpack_packer* pk, msgpack_object d)
|
||||
{
|
||||
switch(d.type) {
|
||||
case MSGPACK_OBJECT_NIL:
|
||||
return msgpack_pack_nil(pk);
|
||||
|
||||
case MSGPACK_OBJECT_BOOLEAN:
|
||||
if(d.via.boolean) {
|
||||
return msgpack_pack_true(pk);
|
||||
} else {
|
||||
return msgpack_pack_false(pk);
|
||||
}
|
||||
|
||||
case MSGPACK_OBJECT_POSITIVE_INTEGER:
|
||||
return msgpack_pack_uint64(pk, d.via.u64);
|
||||
|
||||
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
|
||||
return msgpack_pack_int64(pk, d.via.i64);
|
||||
|
||||
case MSGPACK_OBJECT_FLOAT32:
|
||||
return msgpack_pack_float(pk, (float)d.via.f64);
|
||||
|
||||
case MSGPACK_OBJECT_FLOAT64:
|
||||
return msgpack_pack_double(pk, d.via.f64);
|
||||
|
||||
case MSGPACK_OBJECT_STR:
|
||||
{
|
||||
int ret = msgpack_pack_str(pk, d.via.str.size);
|
||||
if(ret < 0) { return ret; }
|
||||
return msgpack_pack_str_body(pk, d.via.str.ptr, d.via.str.size);
|
||||
}
|
||||
|
||||
case MSGPACK_OBJECT_BIN:
|
||||
{
|
||||
int ret = msgpack_pack_bin(pk, d.via.bin.size);
|
||||
if(ret < 0) { return ret; }
|
||||
return msgpack_pack_bin_body(pk, d.via.bin.ptr, d.via.bin.size);
|
||||
}
|
||||
|
||||
case MSGPACK_OBJECT_EXT:
|
||||
{
|
||||
int ret = msgpack_pack_ext(pk, d.via.ext.size, d.via.ext.type);
|
||||
if(ret < 0) { return ret; }
|
||||
return msgpack_pack_ext_body(pk, d.via.ext.ptr, d.via.ext.size);
|
||||
}
|
||||
|
||||
case MSGPACK_OBJECT_ARRAY:
|
||||
{
|
||||
int ret = msgpack_pack_array(pk, d.via.array.size);
|
||||
if(ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
msgpack_object* o = d.via.array.ptr;
|
||||
msgpack_object* const oend = d.via.array.ptr + d.via.array.size;
|
||||
for(; o != oend; ++o) {
|
||||
ret = msgpack_pack_object(pk, *o);
|
||||
if(ret < 0) { return ret; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
case MSGPACK_OBJECT_MAP:
|
||||
{
|
||||
int ret = msgpack_pack_map(pk, d.via.map.size);
|
||||
if(ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
msgpack_object_kv* kv = d.via.map.ptr;
|
||||
msgpack_object_kv* const kvend = d.via.map.ptr + d.via.map.size;
|
||||
for(; kv != kvend; ++kv) {
|
||||
ret = msgpack_pack_object(pk, kv->key);
|
||||
if(ret < 0) { return ret; }
|
||||
ret = msgpack_pack_object(pk, kv->val);
|
||||
if(ret < 0) { return ret; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_KERNEL_MODE)
|
||||
|
||||
static void msgpack_object_bin_print(FILE* out, const char *ptr, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (ptr[i] == '"') {
|
||||
fputs("\\\"", out);
|
||||
} else if (isprint((unsigned char)ptr[i])) {
|
||||
fputc(ptr[i], out);
|
||||
} else {
|
||||
fprintf(out, "\\x%02x", (unsigned char)ptr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void msgpack_object_print(FILE* out, msgpack_object o)
|
||||
{
|
||||
switch(o.type) {
|
||||
case MSGPACK_OBJECT_NIL:
|
||||
fprintf(out, "nil");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_BOOLEAN:
|
||||
fprintf(out, (o.via.boolean ? "true" : "false"));
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_POSITIVE_INTEGER:
|
||||
#if defined(PRIu64)
|
||||
fprintf(out, "%" PRIu64, o.via.u64);
|
||||
#else
|
||||
if (o.via.u64 > ULONG_MAX)
|
||||
fprintf(out, "over 4294967295");
|
||||
else
|
||||
fprintf(out, "%lu", (unsigned long)o.via.u64);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
|
||||
#if defined(PRIi64)
|
||||
fprintf(out, "%" PRIi64, o.via.i64);
|
||||
#else
|
||||
if (o.via.i64 > LONG_MAX)
|
||||
fprintf(out, "over +2147483647");
|
||||
else if (o.via.i64 < LONG_MIN)
|
||||
fprintf(out, "under -2147483648");
|
||||
else
|
||||
fprintf(out, "%ld", (signed long)o.via.i64);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_FLOAT32:
|
||||
case MSGPACK_OBJECT_FLOAT64:
|
||||
fprintf(out, "%f", o.via.f64);
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_STR:
|
||||
fprintf(out, "\"");
|
||||
fwrite(o.via.str.ptr, o.via.str.size, 1, out);
|
||||
fprintf(out, "\"");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_BIN:
|
||||
fprintf(out, "\"");
|
||||
msgpack_object_bin_print(out, o.via.bin.ptr, o.via.bin.size);
|
||||
fprintf(out, "\"");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_EXT:
|
||||
#if defined(PRIi8)
|
||||
fprintf(out, "(ext: %" PRIi8 ")", o.via.ext.type);
|
||||
#else
|
||||
fprintf(out, "(ext: %d)", (int)o.via.ext.type);
|
||||
#endif
|
||||
fprintf(out, "\"");
|
||||
msgpack_object_bin_print(out, o.via.ext.ptr, o.via.ext.size);
|
||||
fprintf(out, "\"");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_ARRAY:
|
||||
fprintf(out, "[");
|
||||
if(o.via.array.size != 0) {
|
||||
msgpack_object* p = o.via.array.ptr;
|
||||
msgpack_object* const pend = o.via.array.ptr + o.via.array.size;
|
||||
msgpack_object_print(out, *p);
|
||||
++p;
|
||||
for(; p < pend; ++p) {
|
||||
fprintf(out, ", ");
|
||||
msgpack_object_print(out, *p);
|
||||
}
|
||||
}
|
||||
fprintf(out, "]");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_MAP:
|
||||
fprintf(out, "{");
|
||||
if(o.via.map.size != 0) {
|
||||
msgpack_object_kv* p = o.via.map.ptr;
|
||||
msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size;
|
||||
msgpack_object_print(out, p->key);
|
||||
fprintf(out, "=>");
|
||||
msgpack_object_print(out, p->val);
|
||||
++p;
|
||||
for(; p < pend; ++p) {
|
||||
fprintf(out, ", ");
|
||||
msgpack_object_print(out, p->key);
|
||||
fprintf(out, "=>");
|
||||
msgpack_object_print(out, p->val);
|
||||
}
|
||||
}
|
||||
fprintf(out, "}");
|
||||
break;
|
||||
|
||||
default:
|
||||
// FIXME
|
||||
#if defined(PRIu64)
|
||||
fprintf(out, "#<UNKNOWN %i %" PRIu64 ">", o.type, o.via.u64);
|
||||
#else
|
||||
if (o.via.u64 > ULONG_MAX)
|
||||
fprintf(out, "#<UNKNOWN %i over 4294967295>", o.type);
|
||||
else
|
||||
fprintf(out, "#<UNKNOWN %i %lu>", o.type, (unsigned long)o.via.u64);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define MSGPACK_CHECKED_CALL(ret, func, aux_buffer, aux_buffer_size, ...) \
|
||||
ret = func(aux_buffer, aux_buffer_size, __VA_ARGS__); \
|
||||
if (ret <= 0 || ret >= (int)aux_buffer_size) return 0; \
|
||||
aux_buffer = aux_buffer + ret; \
|
||||
aux_buffer_size = aux_buffer_size - ret \
|
||||
|
||||
static int msgpack_object_bin_print_buffer(char *buffer, size_t buffer_size, const char *ptr, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
char *aux_buffer = buffer;
|
||||
size_t aux_buffer_size = buffer_size;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (ptr[i] == '"') {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\\\"");
|
||||
} else if (isprint((unsigned char)ptr[i])) {
|
||||
if (aux_buffer_size > 0) {
|
||||
memcpy(aux_buffer, ptr + i, 1);
|
||||
aux_buffer = aux_buffer + 1;
|
||||
aux_buffer_size = aux_buffer_size - 1;
|
||||
}
|
||||
} else {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\\x%02x", (unsigned char)ptr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)(buffer_size - aux_buffer_size);
|
||||
}
|
||||
|
||||
int msgpack_object_print_buffer(char *buffer, size_t buffer_size, msgpack_object o)
|
||||
{
|
||||
char *aux_buffer = buffer;
|
||||
size_t aux_buffer_size = buffer_size;
|
||||
int ret;
|
||||
switch(o.type) {
|
||||
case MSGPACK_OBJECT_NIL:
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "nil");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_BOOLEAN:
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, (o.via.boolean ? "true" : "false"));
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_POSITIVE_INTEGER:
|
||||
#if defined(PRIu64)
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%" PRIu64, o.via.u64);
|
||||
#else
|
||||
if (o.via.u64 > ULONG_MAX) {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "over 4294967295");
|
||||
} else {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%lu", (unsigned long)o.via.u64);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
|
||||
#if defined(PRIi64)
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%" PRIi64, o.via.i64);
|
||||
#else
|
||||
if (o.via.i64 > LONG_MAX) {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "over +2147483647");
|
||||
} else if (o.via.i64 < LONG_MIN) {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "under -2147483648");
|
||||
} else {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%ld", (signed long)o.via.i64);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_FLOAT32:
|
||||
case MSGPACK_OBJECT_FLOAT64:
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%f", o.via.f64);
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_STR:
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
|
||||
if (o.via.str.size > 0) {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "%.*s", (int)o.via.str.size, o.via.str.ptr);
|
||||
}
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_BIN:
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
|
||||
MSGPACK_CHECKED_CALL(ret, msgpack_object_bin_print_buffer, aux_buffer, aux_buffer_size, o.via.bin.ptr, o.via.bin.size);
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_EXT:
|
||||
#if defined(PRIi8)
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "(ext: %" PRIi8 ")", o.via.ext.type);
|
||||
#else
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "(ext: %d)", (int)o.via.ext.type);
|
||||
#endif
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
|
||||
MSGPACK_CHECKED_CALL(ret, msgpack_object_bin_print_buffer, aux_buffer, aux_buffer_size, o.via.ext.ptr, o.via.ext.size);
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "\"");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_ARRAY:
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "[");
|
||||
if(o.via.array.size != 0) {
|
||||
msgpack_object* p = o.via.array.ptr;
|
||||
msgpack_object* const pend = o.via.array.ptr + o.via.array.size;
|
||||
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, *p);
|
||||
++p;
|
||||
for(; p < pend; ++p) {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, ", ");
|
||||
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, *p);
|
||||
}
|
||||
}
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "]");
|
||||
break;
|
||||
|
||||
case MSGPACK_OBJECT_MAP:
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "{");
|
||||
if(o.via.map.size != 0) {
|
||||
msgpack_object_kv* p = o.via.map.ptr;
|
||||
msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size;
|
||||
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->key);
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "=>");
|
||||
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->val);
|
||||
++p;
|
||||
for(; p < pend; ++p) {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, ", ");
|
||||
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->key);
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "=>");
|
||||
MSGPACK_CHECKED_CALL(ret, msgpack_object_print_buffer, aux_buffer, aux_buffer_size, p->val);
|
||||
}
|
||||
}
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "}");
|
||||
break;
|
||||
|
||||
default:
|
||||
// FIXME
|
||||
#if defined(PRIu64)
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "#<UNKNOWN %i %" PRIu64 ">", o.type, o.via.u64);
|
||||
#else
|
||||
if (o.via.u64 > ULONG_MAX) {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "#<UNKNOWN %i over 4294967295>", o.type);
|
||||
} else {
|
||||
MSGPACK_CHECKED_CALL(ret, snprintf, aux_buffer, aux_buffer_size, "#<UNKNOWN %i %lu>", o.type, (unsigned long)o.via.u64);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return (int)(buffer_size - aux_buffer_size);
|
||||
}
|
||||
|
||||
#undef MSGPACK_CHECKED_CALL
|
||||
|
||||
bool msgpack_object_equal(const msgpack_object x, const msgpack_object y)
|
||||
{
|
||||
if(x.type != y.type) { return false; }
|
||||
|
||||
switch(x.type) {
|
||||
case MSGPACK_OBJECT_NIL:
|
||||
return true;
|
||||
|
||||
case MSGPACK_OBJECT_BOOLEAN:
|
||||
return x.via.boolean == y.via.boolean;
|
||||
|
||||
case MSGPACK_OBJECT_POSITIVE_INTEGER:
|
||||
return x.via.u64 == y.via.u64;
|
||||
|
||||
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
|
||||
return x.via.i64 == y.via.i64;
|
||||
|
||||
case MSGPACK_OBJECT_FLOAT32:
|
||||
case MSGPACK_OBJECT_FLOAT64:
|
||||
return x.via.f64 == y.via.f64;
|
||||
|
||||
case MSGPACK_OBJECT_STR:
|
||||
return x.via.str.size == y.via.str.size &&
|
||||
memcmp(x.via.str.ptr, y.via.str.ptr, x.via.str.size) == 0;
|
||||
|
||||
case MSGPACK_OBJECT_BIN:
|
||||
return x.via.bin.size == y.via.bin.size &&
|
||||
memcmp(x.via.bin.ptr, y.via.bin.ptr, x.via.bin.size) == 0;
|
||||
|
||||
case MSGPACK_OBJECT_EXT:
|
||||
return x.via.ext.size == y.via.ext.size &&
|
||||
x.via.ext.type == y.via.ext.type &&
|
||||
memcmp(x.via.ext.ptr, y.via.ext.ptr, x.via.ext.size) == 0;
|
||||
|
||||
case MSGPACK_OBJECT_ARRAY:
|
||||
if(x.via.array.size != y.via.array.size) {
|
||||
return false;
|
||||
} else if(x.via.array.size == 0) {
|
||||
return true;
|
||||
} else {
|
||||
msgpack_object* px = x.via.array.ptr;
|
||||
msgpack_object* const pxend = x.via.array.ptr + x.via.array.size;
|
||||
msgpack_object* py = y.via.array.ptr;
|
||||
do {
|
||||
if(!msgpack_object_equal(*px, *py)) {
|
||||
return false;
|
||||
}
|
||||
++px;
|
||||
++py;
|
||||
} while(px < pxend);
|
||||
return true;
|
||||
}
|
||||
|
||||
case MSGPACK_OBJECT_MAP:
|
||||
if(x.via.map.size != y.via.map.size) {
|
||||
return false;
|
||||
} else if(x.via.map.size == 0) {
|
||||
return true;
|
||||
} else {
|
||||
msgpack_object_kv* px = x.via.map.ptr;
|
||||
msgpack_object_kv* const pxend = x.via.map.ptr + x.via.map.size;
|
||||
msgpack_object_kv* py = y.via.map.ptr;
|
||||
do {
|
||||
if(!msgpack_object_equal(px->key, py->key) || !msgpack_object_equal(px->val, py->val)) {
|
||||
return false;
|
||||
}
|
||||
++px;
|
||||
++py;
|
||||
} while(px < pxend);
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
702
local_pod_repo/msgpack-c/msgpack-c/src/unpack.c
Normal file
702
local_pod_repo/msgpack-c/msgpack-c/src/unpack.c
Normal file
@@ -0,0 +1,702 @@
|
||||
/*
|
||||
* MessagePack for C unpacking routine
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#include "unpack.h"
|
||||
#include "unpack_define.h"
|
||||
#include "util.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _msgpack_atomic_counter_header
|
||||
#include _msgpack_atomic_counter_header
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
msgpack_zone** z;
|
||||
bool referenced;
|
||||
} unpack_user;
|
||||
|
||||
|
||||
#define msgpack_unpack_struct(name) \
|
||||
struct template ## name
|
||||
|
||||
#define msgpack_unpack_func(ret, name) \
|
||||
ret template ## name
|
||||
|
||||
#define msgpack_unpack_callback(name) \
|
||||
template_callback ## name
|
||||
|
||||
#define msgpack_unpack_object msgpack_object
|
||||
|
||||
#define msgpack_unpack_user unpack_user
|
||||
|
||||
|
||||
struct template_context;
|
||||
typedef struct template_context template_context;
|
||||
|
||||
static void template_init(template_context* ctx);
|
||||
|
||||
static msgpack_object template_data(template_context* ctx);
|
||||
|
||||
static int template_execute(
|
||||
template_context* ctx, const char* data, size_t len, size_t* off);
|
||||
|
||||
|
||||
static inline msgpack_object template_callback_root(unpack_user* u)
|
||||
{
|
||||
msgpack_object o;
|
||||
MSGPACK_UNUSED(u);
|
||||
o.type = MSGPACK_OBJECT_NIL;
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline int template_callback_uint8(unpack_user* u, uint8_t d, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
|
||||
o->via.u64 = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_uint16(unpack_user* u, uint16_t d, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
|
||||
o->via.u64 = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_uint32(unpack_user* u, uint32_t d, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
|
||||
o->via.u64 = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_uint64(unpack_user* u, uint64_t d, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
|
||||
o->via.u64 = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_int8(unpack_user* u, int8_t d, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
if(d >= 0) {
|
||||
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
|
||||
o->via.u64 = (uint64_t)d;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER;
|
||||
o->via.i64 = d;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int template_callback_int16(unpack_user* u, int16_t d, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
if(d >= 0) {
|
||||
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
|
||||
o->via.u64 = (uint64_t)d;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER;
|
||||
o->via.i64 = d;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int template_callback_int32(unpack_user* u, int32_t d, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
if(d >= 0) {
|
||||
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
|
||||
o->via.u64 = (uint64_t)d;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER;
|
||||
o->via.i64 = d;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int template_callback_int64(unpack_user* u, int64_t d, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
if(d >= 0) {
|
||||
o->type = MSGPACK_OBJECT_POSITIVE_INTEGER;
|
||||
o->via.u64 = (uint64_t)d;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER;
|
||||
o->via.i64 = d;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int template_callback_float(unpack_user* u, float d, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
o->type = MSGPACK_OBJECT_FLOAT32;
|
||||
o->via.f64 = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_double(unpack_user* u, double d, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
o->type = MSGPACK_OBJECT_FLOAT64;
|
||||
o->via.f64 = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_nil(unpack_user* u, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
o->type = MSGPACK_OBJECT_NIL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_true(unpack_user* u, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
o->type = MSGPACK_OBJECT_BOOLEAN;
|
||||
o->via.boolean = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_false(unpack_user* u, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
o->type = MSGPACK_OBJECT_BOOLEAN;
|
||||
o->via.boolean = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_array(unpack_user* u, unsigned int n, msgpack_object* o)
|
||||
{
|
||||
size_t size;
|
||||
// Let's leverage the fact that sizeof(msgpack_object) is a compile time constant
|
||||
// to check for int overflows.
|
||||
// Note - while n is constrained to 32-bit, the product of n * sizeof(msgpack_object)
|
||||
// might not be constrained to 4GB on 64-bit systems
|
||||
#if SIZE_MAX == UINT_MAX
|
||||
if (n > SIZE_MAX/sizeof(msgpack_object))
|
||||
return MSGPACK_UNPACK_NOMEM_ERROR;
|
||||
#endif
|
||||
|
||||
o->type = MSGPACK_OBJECT_ARRAY;
|
||||
o->via.array.size = 0;
|
||||
|
||||
size = n * sizeof(msgpack_object);
|
||||
|
||||
if (*u->z == NULL) {
|
||||
*u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(*u->z == NULL) {
|
||||
return MSGPACK_UNPACK_NOMEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Unsure whether size = 0 should be an error, and if so, what to return
|
||||
o->via.array.ptr = (msgpack_object*)msgpack_zone_malloc(*u->z, size);
|
||||
if(o->via.array.ptr == NULL) { return MSGPACK_UNPACK_NOMEM_ERROR; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_array_item(unpack_user* u, msgpack_object* c, msgpack_object o)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
memcpy(&c->via.array.ptr[c->via.array.size], &o, sizeof(msgpack_object));
|
||||
#else /* __GNUC__ && !__clang__ */
|
||||
c->via.array.ptr[c->via.array.size] = o;
|
||||
#endif /* __GNUC__ && !__clang__ */
|
||||
++c->via.array.size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_map(unpack_user* u, unsigned int n, msgpack_object* o)
|
||||
{
|
||||
size_t size;
|
||||
// Let's leverage the fact that sizeof(msgpack_object_kv) is a compile time constant
|
||||
// to check for int overflows
|
||||
// Note - while n is constrained to 32-bit, the product of n * sizeof(msgpack_object)
|
||||
// might not be constrained to 4GB on 64-bit systems
|
||||
|
||||
// Note - this will always be false on 64-bit systems
|
||||
#if SIZE_MAX == UINT_MAX
|
||||
if (n > SIZE_MAX/sizeof(msgpack_object_kv))
|
||||
return MSGPACK_UNPACK_NOMEM_ERROR;
|
||||
#endif
|
||||
|
||||
o->type = MSGPACK_OBJECT_MAP;
|
||||
o->via.map.size = 0;
|
||||
|
||||
size = n * sizeof(msgpack_object_kv);
|
||||
|
||||
if (*u->z == NULL) {
|
||||
*u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(*u->z == NULL) {
|
||||
return MSGPACK_UNPACK_NOMEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Should size = 0 be an error? If so, what error to return?
|
||||
o->via.map.ptr = (msgpack_object_kv*)msgpack_zone_malloc(*u->z, size);
|
||||
if(o->via.map.ptr == NULL) { return MSGPACK_UNPACK_NOMEM_ERROR; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_map_item(unpack_user* u, msgpack_object* c, msgpack_object k, msgpack_object v)
|
||||
{
|
||||
MSGPACK_UNUSED(u);
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
memcpy(&c->via.map.ptr[c->via.map.size].key, &k, sizeof(msgpack_object));
|
||||
memcpy(&c->via.map.ptr[c->via.map.size].val, &v, sizeof(msgpack_object));
|
||||
#else /* __GNUC__ && !__clang__ */
|
||||
c->via.map.ptr[c->via.map.size].key = k;
|
||||
c->via.map.ptr[c->via.map.size].val = v;
|
||||
#endif /* __GNUC__ && !__clang__ */
|
||||
++c->via.map.size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_str(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(b);
|
||||
if (*u->z == NULL) {
|
||||
*u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(*u->z == NULL) {
|
||||
return MSGPACK_UNPACK_NOMEM_ERROR;
|
||||
}
|
||||
}
|
||||
o->type = MSGPACK_OBJECT_STR;
|
||||
o->via.str.ptr = p;
|
||||
o->via.str.size = l;
|
||||
u->referenced = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_bin(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(b);
|
||||
if (*u->z == NULL) {
|
||||
*u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(*u->z == NULL) {
|
||||
return MSGPACK_UNPACK_NOMEM_ERROR;
|
||||
}
|
||||
}
|
||||
o->type = MSGPACK_OBJECT_BIN;
|
||||
o->via.bin.ptr = p;
|
||||
o->via.bin.size = l;
|
||||
u->referenced = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_ext(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o)
|
||||
{
|
||||
MSGPACK_UNUSED(b);
|
||||
if (l == 0) {
|
||||
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||
}
|
||||
if (*u->z == NULL) {
|
||||
*u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(*u->z == NULL) {
|
||||
return MSGPACK_UNPACK_NOMEM_ERROR;
|
||||
}
|
||||
}
|
||||
o->type = MSGPACK_OBJECT_EXT;
|
||||
o->via.ext.type = *p;
|
||||
o->via.ext.ptr = p + 1;
|
||||
o->via.ext.size = l - 1;
|
||||
u->referenced = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "unpack_template.h"
|
||||
|
||||
|
||||
#define CTX_CAST(m) ((template_context*)(m))
|
||||
#define CTX_REFERENCED(mpac) CTX_CAST((mpac)->ctx)->user.referenced
|
||||
|
||||
#define COUNTER_SIZE (sizeof(_msgpack_atomic_counter_t))
|
||||
|
||||
|
||||
static inline void init_count(void* buffer)
|
||||
{
|
||||
*(volatile _msgpack_atomic_counter_t*)buffer = 1;
|
||||
}
|
||||
|
||||
static inline void decr_count(void* buffer)
|
||||
{
|
||||
// atomic if(--*(_msgpack_atomic_counter_t*)buffer == 0) { free(buffer); }
|
||||
if(_msgpack_sync_decr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer) == 0) {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void incr_count(void* buffer)
|
||||
{
|
||||
// atomic ++*(_msgpack_atomic_counter_t*)buffer;
|
||||
_msgpack_sync_incr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer);
|
||||
}
|
||||
|
||||
static inline _msgpack_atomic_counter_t get_count(void* buffer)
|
||||
{
|
||||
return *(volatile _msgpack_atomic_counter_t*)buffer;
|
||||
}
|
||||
|
||||
bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size)
|
||||
{
|
||||
char* buffer;
|
||||
void* ctx;
|
||||
|
||||
if(initial_buffer_size < COUNTER_SIZE) {
|
||||
initial_buffer_size = COUNTER_SIZE;
|
||||
}
|
||||
|
||||
buffer = (char*)malloc(initial_buffer_size);
|
||||
if(buffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx = malloc(sizeof(template_context));
|
||||
if(ctx == NULL) {
|
||||
free(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
mpac->buffer = buffer;
|
||||
mpac->used = COUNTER_SIZE;
|
||||
mpac->free = initial_buffer_size - mpac->used;
|
||||
mpac->off = COUNTER_SIZE;
|
||||
mpac->parsed = 0;
|
||||
mpac->initial_buffer_size = initial_buffer_size;
|
||||
mpac->z = NULL;
|
||||
mpac->ctx = ctx;
|
||||
|
||||
init_count(mpac->buffer);
|
||||
|
||||
template_init(CTX_CAST(mpac->ctx));
|
||||
CTX_CAST(mpac->ctx)->user.z = &mpac->z;
|
||||
CTX_CAST(mpac->ctx)->user.referenced = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void msgpack_unpacker_destroy(msgpack_unpacker* mpac)
|
||||
{
|
||||
msgpack_zone_free(mpac->z);
|
||||
free(mpac->ctx);
|
||||
decr_count(mpac->buffer);
|
||||
}
|
||||
|
||||
msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size)
|
||||
{
|
||||
msgpack_unpacker* mpac = (msgpack_unpacker*)malloc(sizeof(msgpack_unpacker));
|
||||
if(mpac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!msgpack_unpacker_init(mpac, initial_buffer_size)) {
|
||||
free(mpac);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mpac;
|
||||
}
|
||||
|
||||
void msgpack_unpacker_free(msgpack_unpacker* mpac)
|
||||
{
|
||||
msgpack_unpacker_destroy(mpac);
|
||||
free(mpac);
|
||||
}
|
||||
|
||||
bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size)
|
||||
{
|
||||
if(mpac->used == mpac->off && get_count(mpac->buffer) == 1
|
||||
&& !CTX_REFERENCED(mpac)) {
|
||||
// rewind buffer
|
||||
mpac->free += mpac->used - COUNTER_SIZE;
|
||||
mpac->used = COUNTER_SIZE;
|
||||
mpac->off = COUNTER_SIZE;
|
||||
|
||||
if(mpac->free >= size) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(mpac->off == COUNTER_SIZE) {
|
||||
char* tmp;
|
||||
size_t next_size = (mpac->used + mpac->free) * 2; // include COUNTER_SIZE
|
||||
while(next_size < size + mpac->used) {
|
||||
size_t tmp_next_size = next_size * 2;
|
||||
if (tmp_next_size <= next_size) {
|
||||
next_size = size + mpac->used;
|
||||
break;
|
||||
}
|
||||
next_size = tmp_next_size;
|
||||
}
|
||||
|
||||
tmp = (char*)realloc(mpac->buffer, next_size);
|
||||
if(tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mpac->buffer = tmp;
|
||||
mpac->free = next_size - mpac->used;
|
||||
|
||||
} else {
|
||||
char* tmp;
|
||||
size_t next_size = mpac->initial_buffer_size; // include COUNTER_SIZE
|
||||
size_t not_parsed = mpac->used - mpac->off;
|
||||
while(next_size < size + not_parsed + COUNTER_SIZE) {
|
||||
size_t tmp_next_size = next_size * 2;
|
||||
if (tmp_next_size <= next_size) {
|
||||
next_size = size + not_parsed + COUNTER_SIZE;
|
||||
break;
|
||||
}
|
||||
next_size = tmp_next_size;
|
||||
}
|
||||
|
||||
tmp = (char*)malloc(next_size);
|
||||
if(tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
init_count(tmp);
|
||||
|
||||
memcpy(tmp+COUNTER_SIZE, mpac->buffer+mpac->off, not_parsed);
|
||||
|
||||
if(CTX_REFERENCED(mpac)) {
|
||||
if(!msgpack_zone_push_finalizer(mpac->z, decr_count, mpac->buffer)) {
|
||||
free(tmp);
|
||||
return false;
|
||||
}
|
||||
CTX_REFERENCED(mpac) = false;
|
||||
} else {
|
||||
decr_count(mpac->buffer);
|
||||
}
|
||||
|
||||
mpac->buffer = tmp;
|
||||
mpac->used = not_parsed + COUNTER_SIZE;
|
||||
mpac->free = next_size - mpac->used;
|
||||
mpac->off = COUNTER_SIZE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int msgpack_unpacker_execute(msgpack_unpacker* mpac)
|
||||
{
|
||||
size_t off = mpac->off;
|
||||
int ret = template_execute(CTX_CAST(mpac->ctx),
|
||||
mpac->buffer, mpac->used, &mpac->off);
|
||||
if(mpac->off > off) {
|
||||
mpac->parsed += mpac->off - off;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac)
|
||||
{
|
||||
return template_data(CTX_CAST(mpac->ctx));
|
||||
}
|
||||
|
||||
msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac)
|
||||
{
|
||||
msgpack_zone* old = mpac->z;
|
||||
|
||||
if (old == NULL) return NULL;
|
||||
if(!msgpack_unpacker_flush_zone(mpac)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mpac->z = NULL;
|
||||
CTX_CAST(mpac->ctx)->user.z = &mpac->z;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac)
|
||||
{
|
||||
msgpack_zone_clear(mpac->z);
|
||||
}
|
||||
|
||||
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac)
|
||||
{
|
||||
if(CTX_REFERENCED(mpac)) {
|
||||
if(!msgpack_zone_push_finalizer(mpac->z, decr_count, mpac->buffer)) {
|
||||
return false;
|
||||
}
|
||||
CTX_REFERENCED(mpac) = false;
|
||||
|
||||
incr_count(mpac->buffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void msgpack_unpacker_reset(msgpack_unpacker* mpac)
|
||||
{
|
||||
template_init(CTX_CAST(mpac->ctx));
|
||||
// don't reset referenced flag
|
||||
mpac->parsed = 0;
|
||||
}
|
||||
|
||||
static inline msgpack_unpack_return unpacker_next(msgpack_unpacker* mpac,
|
||||
msgpack_unpacked* result)
|
||||
{
|
||||
int ret;
|
||||
|
||||
msgpack_unpacked_destroy(result);
|
||||
|
||||
ret = msgpack_unpacker_execute(mpac);
|
||||
|
||||
if(ret < 0) {
|
||||
result->zone = NULL;
|
||||
memset(&result->data, 0, sizeof(msgpack_object));
|
||||
return (msgpack_unpack_return)ret;
|
||||
}
|
||||
|
||||
if(ret == 0) {
|
||||
return MSGPACK_UNPACK_CONTINUE;
|
||||
}
|
||||
result->zone = msgpack_unpacker_release_zone(mpac);
|
||||
result->data = msgpack_unpacker_data(mpac);
|
||||
|
||||
return MSGPACK_UNPACK_SUCCESS;
|
||||
}
|
||||
|
||||
msgpack_unpack_return msgpack_unpacker_next(msgpack_unpacker* mpac,
|
||||
msgpack_unpacked* result)
|
||||
{
|
||||
msgpack_unpack_return ret;
|
||||
|
||||
ret = unpacker_next(mpac, result);
|
||||
if (ret == MSGPACK_UNPACK_SUCCESS) {
|
||||
msgpack_unpacker_reset(mpac);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
msgpack_unpack_return
|
||||
msgpack_unpacker_next_with_size(msgpack_unpacker* mpac,
|
||||
msgpack_unpacked* result, size_t *p_bytes)
|
||||
{
|
||||
msgpack_unpack_return ret;
|
||||
|
||||
ret = unpacker_next(mpac, result);
|
||||
if (ret == MSGPACK_UNPACK_SUCCESS || ret == MSGPACK_UNPACK_CONTINUE) {
|
||||
*p_bytes = mpac->parsed;
|
||||
}
|
||||
|
||||
if (ret == MSGPACK_UNPACK_SUCCESS) {
|
||||
msgpack_unpacker_reset(mpac);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
msgpack_unpack_return
|
||||
msgpack_unpack(const char* data, size_t len, size_t* off,
|
||||
msgpack_zone* result_zone, msgpack_object* result)
|
||||
{
|
||||
size_t noff = 0;
|
||||
if(off != NULL) { noff = *off; }
|
||||
|
||||
if(len <= noff) {
|
||||
// FIXME
|
||||
return MSGPACK_UNPACK_CONTINUE;
|
||||
}
|
||||
else {
|
||||
int e;
|
||||
template_context ctx;
|
||||
template_init(&ctx);
|
||||
|
||||
ctx.user.z = &result_zone;
|
||||
ctx.user.referenced = false;
|
||||
|
||||
e = template_execute(&ctx, data, len, &noff);
|
||||
if(e < 0) {
|
||||
return (msgpack_unpack_return)e;
|
||||
}
|
||||
|
||||
if(off != NULL) { *off = noff; }
|
||||
|
||||
if(e == 0) {
|
||||
return MSGPACK_UNPACK_CONTINUE;
|
||||
}
|
||||
|
||||
*result = template_data(&ctx);
|
||||
|
||||
if(noff < len) {
|
||||
return MSGPACK_UNPACK_EXTRA_BYTES;
|
||||
}
|
||||
|
||||
return MSGPACK_UNPACK_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
msgpack_unpack_return
|
||||
msgpack_unpack_next(msgpack_unpacked* result,
|
||||
const char* data, size_t len, size_t* off)
|
||||
{
|
||||
size_t noff = 0;
|
||||
msgpack_unpacked_destroy(result);
|
||||
|
||||
if(off != NULL) { noff = *off; }
|
||||
|
||||
if(len <= noff) {
|
||||
return MSGPACK_UNPACK_CONTINUE;
|
||||
}
|
||||
|
||||
{
|
||||
int e;
|
||||
template_context ctx;
|
||||
template_init(&ctx);
|
||||
|
||||
ctx.user.z = &result->zone;
|
||||
ctx.user.referenced = false;
|
||||
|
||||
e = template_execute(&ctx, data, len, &noff);
|
||||
|
||||
if(off != NULL) { *off = noff; }
|
||||
|
||||
if(e < 0) {
|
||||
msgpack_zone_free(result->zone);
|
||||
result->zone = NULL;
|
||||
return (msgpack_unpack_return)e;
|
||||
}
|
||||
|
||||
if(e == 0) {
|
||||
return MSGPACK_UNPACK_CONTINUE;
|
||||
}
|
||||
|
||||
result->data = template_data(&ctx);
|
||||
|
||||
return MSGPACK_UNPACK_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MSGPACK_OLD_COMPILER_BUS_ERROR_WORKAROUND)
|
||||
// FIXME: Dirty hack to avoid a bus error caused by OS X's old gcc.
|
||||
static void dummy_function_to_avoid_bus_error()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
22
local_pod_repo/msgpack-c/msgpack-c/src/version.c
Normal file
22
local_pod_repo/msgpack-c/msgpack-c/src/version.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "msgpack.h"
|
||||
|
||||
const char* msgpack_version(void)
|
||||
{
|
||||
return MSGPACK_VERSION;
|
||||
}
|
||||
|
||||
int msgpack_version_major(void)
|
||||
{
|
||||
return MSGPACK_VERSION_MAJOR;
|
||||
}
|
||||
|
||||
int msgpack_version_minor(void)
|
||||
{
|
||||
return MSGPACK_VERSION_MINOR;
|
||||
}
|
||||
|
||||
int msgpack_version_revision(void)
|
||||
{
|
||||
return MSGPACK_VERSION_REVISION;
|
||||
}
|
||||
|
||||
250
local_pod_repo/msgpack-c/msgpack-c/src/vrefbuffer.c
Normal file
250
local_pod_repo/msgpack-c/msgpack-c/src/vrefbuffer.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* MessagePack for C zero-copy buffer implementation
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#include "vrefbuffer.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MSGPACK_PACKER_MAX_BUFFER_SIZE 9
|
||||
|
||||
struct msgpack_vrefbuffer_chunk {
|
||||
struct msgpack_vrefbuffer_chunk* next;
|
||||
/* data ... */
|
||||
};
|
||||
|
||||
bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
|
||||
size_t ref_size, size_t chunk_size)
|
||||
{
|
||||
size_t nfirst;
|
||||
msgpack_iovec* array;
|
||||
msgpack_vrefbuffer_chunk* chunk;
|
||||
|
||||
if (ref_size == 0) {
|
||||
ref_size = MSGPACK_VREFBUFFER_REF_SIZE;
|
||||
}
|
||||
if(chunk_size == 0) {
|
||||
chunk_size = MSGPACK_VREFBUFFER_CHUNK_SIZE;
|
||||
}
|
||||
vbuf->chunk_size = chunk_size;
|
||||
vbuf->ref_size =
|
||||
ref_size > MSGPACK_PACKER_MAX_BUFFER_SIZE + 1 ?
|
||||
ref_size : MSGPACK_PACKER_MAX_BUFFER_SIZE + 1 ;
|
||||
|
||||
if((sizeof(msgpack_vrefbuffer_chunk) + chunk_size) < chunk_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nfirst = (sizeof(msgpack_iovec) < 72/2) ?
|
||||
72 / sizeof(msgpack_iovec) : 8;
|
||||
|
||||
array = (msgpack_iovec*)malloc(
|
||||
sizeof(msgpack_iovec) * nfirst);
|
||||
if(array == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vbuf->tail = array;
|
||||
vbuf->end = array + nfirst;
|
||||
vbuf->array = array;
|
||||
|
||||
chunk = (msgpack_vrefbuffer_chunk*)malloc(
|
||||
sizeof(msgpack_vrefbuffer_chunk) + chunk_size);
|
||||
if(chunk == NULL) {
|
||||
free(array);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
|
||||
|
||||
ib->free = chunk_size;
|
||||
ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
|
||||
ib->head = chunk;
|
||||
chunk->next = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf)
|
||||
{
|
||||
msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head;
|
||||
while(true) {
|
||||
msgpack_vrefbuffer_chunk* n = c->next;
|
||||
free(c);
|
||||
if(n != NULL) {
|
||||
c = n;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(vbuf->array);
|
||||
}
|
||||
|
||||
void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vbuf)
|
||||
{
|
||||
msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head->next;
|
||||
msgpack_vrefbuffer_chunk* n;
|
||||
while(c != NULL) {
|
||||
n = c->next;
|
||||
free(c);
|
||||
c = n;
|
||||
}
|
||||
|
||||
{
|
||||
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
|
||||
msgpack_vrefbuffer_chunk* chunk = ib->head;
|
||||
chunk->next = NULL;
|
||||
ib->free = vbuf->chunk_size;
|
||||
ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
|
||||
|
||||
vbuf->tail = vbuf->array;
|
||||
}
|
||||
}
|
||||
|
||||
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
|
||||
const char* buf, size_t len)
|
||||
{
|
||||
if(vbuf->tail == vbuf->end) {
|
||||
const size_t nused = (size_t)(vbuf->tail - vbuf->array);
|
||||
const size_t nnext = nused * 2;
|
||||
|
||||
msgpack_iovec* nvec = (msgpack_iovec*)realloc(
|
||||
vbuf->array, sizeof(msgpack_iovec)*nnext);
|
||||
if(nvec == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
vbuf->array = nvec;
|
||||
vbuf->end = nvec + nnext;
|
||||
vbuf->tail = nvec + nused;
|
||||
}
|
||||
|
||||
vbuf->tail->iov_base = (char*)buf;
|
||||
vbuf->tail->iov_len = len;
|
||||
++vbuf->tail;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
|
||||
const char* buf, size_t len)
|
||||
{
|
||||
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
|
||||
char* m;
|
||||
|
||||
if(ib->free < len) {
|
||||
msgpack_vrefbuffer_chunk* chunk;
|
||||
size_t sz = vbuf->chunk_size;
|
||||
if(sz < len) {
|
||||
sz = len;
|
||||
}
|
||||
|
||||
if((sizeof(msgpack_vrefbuffer_chunk) + sz) < sz){
|
||||
return -1;
|
||||
}
|
||||
chunk = (msgpack_vrefbuffer_chunk*)malloc(
|
||||
sizeof(msgpack_vrefbuffer_chunk) + sz);
|
||||
if(chunk == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
chunk->next = ib->head;
|
||||
ib->head = chunk;
|
||||
ib->free = sz;
|
||||
ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
|
||||
}
|
||||
|
||||
m = ib->ptr;
|
||||
memcpy(m, buf, len);
|
||||
ib->free -= len;
|
||||
ib->ptr += len;
|
||||
|
||||
if(vbuf->tail != vbuf->array && m ==
|
||||
(const char*)((vbuf->tail-1)->iov_base) + (vbuf->tail-1)->iov_len) {
|
||||
(vbuf->tail-1)->iov_len += len;
|
||||
return 0;
|
||||
} else {
|
||||
return msgpack_vrefbuffer_append_ref(vbuf, m, len);
|
||||
}
|
||||
}
|
||||
|
||||
int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to)
|
||||
{
|
||||
size_t sz = vbuf->chunk_size;
|
||||
msgpack_vrefbuffer_chunk* empty;
|
||||
|
||||
if((sizeof(msgpack_vrefbuffer_chunk) + sz) < sz){
|
||||
return -1;
|
||||
}
|
||||
|
||||
empty = (msgpack_vrefbuffer_chunk*)malloc(
|
||||
sizeof(msgpack_vrefbuffer_chunk) + sz);
|
||||
if(empty == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
empty->next = NULL;
|
||||
|
||||
{
|
||||
const size_t nused = (size_t)(vbuf->tail - vbuf->array);
|
||||
if(to->tail + nused < vbuf->end) {
|
||||
msgpack_iovec* nvec;
|
||||
const size_t tosize = (size_t)(to->tail - to->array);
|
||||
const size_t reqsize = nused + tosize;
|
||||
size_t nnext = (size_t)(to->end - to->array) * 2;
|
||||
while(nnext < reqsize) {
|
||||
size_t tmp_nnext = nnext * 2;
|
||||
if (tmp_nnext <= nnext) {
|
||||
nnext = reqsize;
|
||||
break;
|
||||
}
|
||||
nnext = tmp_nnext;
|
||||
}
|
||||
|
||||
nvec = (msgpack_iovec*)realloc(
|
||||
to->array, sizeof(msgpack_iovec)*nnext);
|
||||
if(nvec == NULL) {
|
||||
free(empty);
|
||||
return -1;
|
||||
}
|
||||
|
||||
to->array = nvec;
|
||||
to->end = nvec + nnext;
|
||||
to->tail = nvec + tosize;
|
||||
}
|
||||
|
||||
memcpy(to->tail, vbuf->array, sizeof(msgpack_iovec)*nused);
|
||||
|
||||
to->tail += nused;
|
||||
vbuf->tail = vbuf->array;
|
||||
|
||||
{
|
||||
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
|
||||
msgpack_vrefbuffer_inner_buffer* const toib = &to->inner_buffer;
|
||||
|
||||
msgpack_vrefbuffer_chunk* last = ib->head;
|
||||
while(last->next != NULL) {
|
||||
last = last->next;
|
||||
}
|
||||
last->next = toib->head;
|
||||
toib->head = ib->head;
|
||||
|
||||
if(toib->free < ib->free) {
|
||||
toib->free = ib->free;
|
||||
toib->ptr = ib->ptr;
|
||||
}
|
||||
|
||||
ib->head = empty;
|
||||
ib->free = sz;
|
||||
ib->ptr = ((char*)empty) + sizeof(msgpack_vrefbuffer_chunk);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
222
local_pod_repo/msgpack-c/msgpack-c/src/zone.c
Normal file
222
local_pod_repo/msgpack-c/msgpack-c/src/zone.c
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* MessagePack for C memory pool implementation
|
||||
*
|
||||
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#include "zone.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct msgpack_zone_chunk {
|
||||
struct msgpack_zone_chunk* next;
|
||||
/* data ... */
|
||||
};
|
||||
|
||||
static inline bool init_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size)
|
||||
{
|
||||
msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc(
|
||||
sizeof(msgpack_zone_chunk) + chunk_size);
|
||||
if(chunk == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cl->head = chunk;
|
||||
cl->free = chunk_size;
|
||||
cl->ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk);
|
||||
chunk->next = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void destroy_chunk_list(msgpack_zone_chunk_list* cl)
|
||||
{
|
||||
msgpack_zone_chunk* c = cl->head;
|
||||
while(true) {
|
||||
msgpack_zone_chunk* n = c->next;
|
||||
free(c);
|
||||
if(n != NULL) {
|
||||
c = n;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void clear_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size)
|
||||
{
|
||||
msgpack_zone_chunk* c = cl->head;
|
||||
while(true) {
|
||||
msgpack_zone_chunk* n = c->next;
|
||||
if(n != NULL) {
|
||||
free(c);
|
||||
c = n;
|
||||
} else {
|
||||
cl->head = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cl->head->next = NULL;
|
||||
cl->free = chunk_size;
|
||||
cl->ptr = ((char*)cl->head) + sizeof(msgpack_zone_chunk);
|
||||
}
|
||||
|
||||
void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size)
|
||||
{
|
||||
msgpack_zone_chunk_list* const cl = &zone->chunk_list;
|
||||
msgpack_zone_chunk* chunk;
|
||||
|
||||
size_t sz = zone->chunk_size;
|
||||
|
||||
while(sz < size) {
|
||||
size_t tmp_sz = sz * 2;
|
||||
if (tmp_sz <= sz) {
|
||||
sz = size;
|
||||
break;
|
||||
}
|
||||
sz = tmp_sz;
|
||||
}
|
||||
|
||||
chunk = (msgpack_zone_chunk*)malloc(
|
||||
sizeof(msgpack_zone_chunk) + sz);
|
||||
if (chunk == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
char* ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk);
|
||||
chunk->next = cl->head;
|
||||
cl->head = chunk;
|
||||
cl->free = sz - size;
|
||||
cl->ptr = ptr + size;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void init_finalizer_array(msgpack_zone_finalizer_array* fa)
|
||||
{
|
||||
fa->tail = NULL;
|
||||
fa->end = NULL;
|
||||
fa->array = NULL;
|
||||
}
|
||||
|
||||
static inline void call_finalizer_array(msgpack_zone_finalizer_array* fa)
|
||||
{
|
||||
msgpack_zone_finalizer* fin = fa->tail;
|
||||
for(; fin != fa->array; --fin) {
|
||||
(*(fin-1)->func)((fin-1)->data);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void destroy_finalizer_array(msgpack_zone_finalizer_array* fa)
|
||||
{
|
||||
call_finalizer_array(fa);
|
||||
free(fa->array);
|
||||
}
|
||||
|
||||
static inline void clear_finalizer_array(msgpack_zone_finalizer_array* fa)
|
||||
{
|
||||
call_finalizer_array(fa);
|
||||
fa->tail = fa->array;
|
||||
}
|
||||
|
||||
bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone,
|
||||
void (*func)(void* data), void* data)
|
||||
{
|
||||
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
|
||||
msgpack_zone_finalizer* tmp;
|
||||
|
||||
const size_t nused = (size_t)(fa->end - fa->array);
|
||||
|
||||
size_t nnext;
|
||||
if(nused == 0) {
|
||||
nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ?
|
||||
72 / sizeof(msgpack_zone_finalizer) : 8;
|
||||
|
||||
} else {
|
||||
nnext = nused * 2;
|
||||
}
|
||||
|
||||
tmp = (msgpack_zone_finalizer*)realloc(fa->array,
|
||||
sizeof(msgpack_zone_finalizer) * nnext);
|
||||
if(tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fa->array = tmp;
|
||||
fa->end = tmp + nnext;
|
||||
fa->tail = tmp + nused;
|
||||
|
||||
fa->tail->func = func;
|
||||
fa->tail->data = data;
|
||||
|
||||
++fa->tail;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool msgpack_zone_is_empty(msgpack_zone* zone)
|
||||
{
|
||||
msgpack_zone_chunk_list* const cl = &zone->chunk_list;
|
||||
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
|
||||
return cl->free == zone->chunk_size && cl->head->next == NULL &&
|
||||
fa->tail == fa->array;
|
||||
}
|
||||
|
||||
|
||||
void msgpack_zone_destroy(msgpack_zone* zone)
|
||||
{
|
||||
destroy_finalizer_array(&zone->finalizer_array);
|
||||
destroy_chunk_list(&zone->chunk_list);
|
||||
}
|
||||
|
||||
void msgpack_zone_clear(msgpack_zone* zone)
|
||||
{
|
||||
clear_finalizer_array(&zone->finalizer_array);
|
||||
clear_chunk_list(&zone->chunk_list, zone->chunk_size);
|
||||
}
|
||||
|
||||
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size)
|
||||
{
|
||||
zone->chunk_size = chunk_size;
|
||||
|
||||
if(!init_chunk_list(&zone->chunk_list, chunk_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
init_finalizer_array(&zone->finalizer_array);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
msgpack_zone* msgpack_zone_new(size_t chunk_size)
|
||||
{
|
||||
msgpack_zone* zone = (msgpack_zone*)malloc(
|
||||
sizeof(msgpack_zone));
|
||||
if(zone == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zone->chunk_size = chunk_size;
|
||||
|
||||
if(!init_chunk_list(&zone->chunk_list, chunk_size)) {
|
||||
free(zone);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
init_finalizer_array(&zone->finalizer_array);
|
||||
|
||||
return zone;
|
||||
}
|
||||
|
||||
void msgpack_zone_free(msgpack_zone* zone)
|
||||
{
|
||||
if(zone == NULL) { return; }
|
||||
msgpack_zone_destroy(zone);
|
||||
free(zone);
|
||||
}
|
||||
31
local_pod_repo/objcTox/.gitignore
vendored
Normal file
31
local_pod_repo/objcTox/.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# Xcode
|
||||
build/*
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
*.xcworkspace
|
||||
!default.xcworkspace
|
||||
xcuserdata
|
||||
profile
|
||||
*.moved-aside
|
||||
*.mode1
|
||||
*.perspective
|
||||
xcshareddata
|
||||
|
||||
# Exclude temp nibs and swap files
|
||||
*~.nib
|
||||
*.swp
|
||||
|
||||
# Exclude OS X folder attributes
|
||||
.DS_Store
|
||||
#
|
||||
# Exclude AppCode files
|
||||
.idea
|
||||
|
||||
Pods
|
||||
Podfile.lock
|
||||
@@ -0,0 +1,33 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTAudioEngine.h"
|
||||
#import "TPCircularBuffer.h"
|
||||
|
||||
@import AVFoundation;
|
||||
|
||||
extern int kBufferLength;
|
||||
extern int kNumberOfChannels;
|
||||
extern int kDefaultSampleRate;
|
||||
extern int kSampleCount_incoming_audio;
|
||||
extern int kSampleCount_outgoing_audio;
|
||||
extern int kBitsPerByte;
|
||||
extern int kFramesPerPacket;
|
||||
extern int kBytesPerSample;
|
||||
extern int kNumberOfAudioQueueBuffers;
|
||||
|
||||
@class OCTAudioQueue;
|
||||
@interface OCTAudioEngine ()
|
||||
|
||||
#if ! TARGET_OS_IPHONE
|
||||
@property (strong, nonatomic, readonly) NSString *inputDeviceID;
|
||||
@property (strong, nonatomic, readonly) NSString *outputDeviceID;
|
||||
#endif
|
||||
|
||||
@property (nonatomic, strong) OCTAudioQueue *outputQueue;
|
||||
@property (nonatomic, strong) OCTAudioQueue *inputQueue;
|
||||
|
||||
- (void)makeQueues:(NSError **)error;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,92 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTToxAV.h"
|
||||
|
||||
@interface OCTAudioEngine : NSObject
|
||||
|
||||
@property (weak, nonatomic) OCTToxAV *toxav;
|
||||
@property (nonatomic, assign) OCTToxFriendNumber friendNumber;
|
||||
|
||||
/**
|
||||
* YES to send audio frames over to tox, otherwise NO.
|
||||
* Default is YES.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL enableMicrophone;
|
||||
|
||||
/**
|
||||
* Starts the Audio Processing Graph.
|
||||
* @param error Pointer to error object.
|
||||
* @return YES on success, otherwise NO.
|
||||
*/
|
||||
- (BOOL)startAudioFlow:(NSError **)error;
|
||||
|
||||
/**
|
||||
* Stops the Audio Processing Graph.
|
||||
* @param error Pointer to error object.
|
||||
* @return YES on success, otherwise NO.
|
||||
*/
|
||||
- (BOOL)stopAudioFlow:(NSError **)error;
|
||||
|
||||
/**
|
||||
* Checks if the Audio Graph is processing.
|
||||
* @param error Pointer to error object.
|
||||
* @return YES if Audio Graph is running, otherwise NO.
|
||||
*/
|
||||
- (BOOL)isAudioRunning:(NSError **)error;
|
||||
|
||||
/**
|
||||
* Provide audio data that will be placed in buffer to be played in speaker.
|
||||
* @param pcm An array of audio samples (sample_count * channels elements).
|
||||
* @param sampleCount The number of audio samples per channel in the PCM array.
|
||||
* @param channels Number of audio channels.
|
||||
* @param sampleRate Sampling rate used in this frame.
|
||||
*/
|
||||
- (void)provideAudioFrames:(OCTToxAVPCMData *)pcm sampleCount:(OCTToxAVSampleCount)sampleCount channels:(OCTToxAVChannels)channels sampleRate:(OCTToxAVSampleRate)sampleRate fromFriend:(OCTToxFriendNumber)friendNumber;
|
||||
|
||||
@end
|
||||
|
||||
#if ! TARGET_OS_IPHONE
|
||||
|
||||
@interface OCTAudioEngine (MacDevice)
|
||||
|
||||
/**
|
||||
* Set the input device (not available on iOS).
|
||||
* @param inputDeviceID Core Audio's unique ID for the device. See
|
||||
* public OCTSubmanagerCalls.h for what these should be.
|
||||
* @param error If this method returns NO, contains more information on the
|
||||
* underlying error.
|
||||
* @return YES on success, otherwise NO.
|
||||
*/
|
||||
- (BOOL)setInputDeviceID:(NSString *)inputDeviceID error:(NSError **)error;
|
||||
|
||||
/**
|
||||
* Set the output device (not available on iOS).
|
||||
* @param outputDeviceID Core Audio's unique ID for the device. See
|
||||
* public OCTSubmanagerCalls.h for what these should be.
|
||||
* @param error If this method returns NO, contains more information on the
|
||||
* underlying error.
|
||||
* @return YES on success, otherwise NO.
|
||||
*/
|
||||
- (BOOL)setOutputDeviceID:(NSString *)outputDeviceID error:(NSError **)error;
|
||||
|
||||
@end
|
||||
|
||||
#else
|
||||
|
||||
@interface OCTAudioEngine (iOSDevice)
|
||||
|
||||
/**
|
||||
* Switch the output to/from the device's speaker.
|
||||
* @param speaker Whether we should use the speaker for output.
|
||||
* @param error If this method returns NO, contains more information on the
|
||||
* underlying error.
|
||||
* @return YES on success, otherwise NO.
|
||||
*/
|
||||
- (BOOL)routeAudioToSpeaker:(BOOL)speaker error:(NSError **)error;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,191 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTAudioEngine+Private.h"
|
||||
#import "OCTToxAV+Private.h"
|
||||
#import "OCTAudioQueue.h"
|
||||
#import "OCTLogging.h"
|
||||
|
||||
@import AVFoundation;
|
||||
|
||||
@interface OCTAudioEngine ()
|
||||
|
||||
@property (nonatomic, assign) OCTToxAVSampleRate outputSampleRate;
|
||||
@property (nonatomic, assign) OCTToxAVChannels outputNumberOfChannels;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTAudioEngine
|
||||
|
||||
#pragma mark - LifeCycle
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_outputSampleRate = kDefaultSampleRate;
|
||||
_outputNumberOfChannels = kNumberOfChannels;
|
||||
_enableMicrophone = YES;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - SPI
|
||||
|
||||
#if ! TARGET_OS_IPHONE
|
||||
|
||||
- (BOOL)setInputDeviceID:(NSString *)inputDeviceID error:(NSError **)error
|
||||
{
|
||||
// if audio is not active, we can't really be bothered to check that the
|
||||
// device exists; we rely on startAudioFlow: to fail later.
|
||||
if (! self.inputQueue) {
|
||||
_inputDeviceID = inputDeviceID;
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([self.inputQueue setDeviceID:inputDeviceID error:error]) {
|
||||
_inputDeviceID = inputDeviceID;
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)setOutputDeviceID:(NSString *)outputDeviceID error:(NSError **)error
|
||||
{
|
||||
if (! self.outputQueue) {
|
||||
_outputDeviceID = outputDeviceID;
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([self.outputQueue setDeviceID:outputDeviceID error:error]) {
|
||||
_outputDeviceID = outputDeviceID;
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
- (BOOL)routeAudioToSpeaker:(BOOL)speaker error:(NSError **)error
|
||||
{
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
|
||||
AVAudioSessionPortOverride override;
|
||||
if (speaker) {
|
||||
override = AVAudioSessionPortOverrideSpeaker;
|
||||
}
|
||||
else {
|
||||
override = AVAudioSessionPortOverrideNone;
|
||||
}
|
||||
|
||||
return [session overrideOutputAudioPort:override error:error];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (BOOL)startAudioFlow:(NSError **)error
|
||||
{
|
||||
#if TARGET_OS_IPHONE
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
|
||||
if (! ([session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:error] &&
|
||||
[session setPreferredSampleRate:kDefaultSampleRate error:error] &&
|
||||
[session setMode:AVAudioSessionModeVoiceChat error:error] &&
|
||||
[session setActive:YES error:error])) {
|
||||
return NO;
|
||||
}
|
||||
#endif
|
||||
|
||||
[self makeQueues:error];
|
||||
|
||||
if (! (self.outputQueue && self.inputQueue)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
OCTAudioEngine *__weak welf = self;
|
||||
self.inputQueue.sendDataBlock = ^(void *data, OCTToxAVSampleCount samples, OCTToxAVSampleRate rate, OCTToxAVChannels channelCount) {
|
||||
OCTAudioEngine *aoi = welf;
|
||||
|
||||
if (aoi.enableMicrophone) {
|
||||
// TOXAUDIO: -outgoing-audio-
|
||||
[aoi.toxav sendAudioFrame:data
|
||||
sampleCount:samples
|
||||
channels:channelCount
|
||||
sampleRate:rate
|
||||
toFriend:aoi.friendNumber
|
||||
error:nil];
|
||||
}
|
||||
};
|
||||
|
||||
// TOXAUDIO: -incoming-audio-
|
||||
[self.outputQueue updateSampleRate:self.outputSampleRate numberOfChannels:self.outputNumberOfChannels error:nil];
|
||||
|
||||
if (! [self.inputQueue begin:error] || ! [self.outputQueue begin:error]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)stopAudioFlow:(NSError **)error
|
||||
{
|
||||
if (! [self.inputQueue stop:error] || ! [self.outputQueue stop:error]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
BOOL ret = [session setActive:NO error:error];
|
||||
#else
|
||||
BOOL ret = YES;
|
||||
#endif
|
||||
|
||||
self.inputQueue = nil;
|
||||
self.outputQueue = nil;
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void)provideAudioFrames:(OCTToxAVPCMData *)pcm sampleCount:(OCTToxAVSampleCount)sampleCount channels:(OCTToxAVChannels)channels sampleRate:(OCTToxAVSampleRate)sampleRate fromFriend:(OCTToxFriendNumber)friendNumber
|
||||
{
|
||||
// TOXAUDIO: -incoming-audio-
|
||||
int32_t len = (int32_t)(channels * sampleCount * sizeof(OCTToxAVPCMData));
|
||||
TPCircularBuffer *buf = [self.outputQueue getBufferPointer];
|
||||
if (buf) {
|
||||
TPCircularBufferProduceBytes(buf, pcm, len);
|
||||
}
|
||||
|
||||
if ((self.outputSampleRate != sampleRate) || (self.outputNumberOfChannels != channels)) {
|
||||
// failure is logged by OCTAudioQueue.
|
||||
[self.outputQueue updateSampleRate:sampleRate numberOfChannels:channels error:nil];
|
||||
|
||||
self.outputSampleRate = sampleRate;
|
||||
self.outputNumberOfChannels = channels;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isAudioRunning:(NSError **)error
|
||||
{
|
||||
return self.inputQueue.running && self.outputQueue.running;
|
||||
}
|
||||
|
||||
- (void)makeQueues:(NSError **)error
|
||||
{
|
||||
// Note: OCTAudioQueue handles the case where the device ids are nil - in that case
|
||||
// we don't set the device explicitly, and the default is used.
|
||||
#if TARGET_OS_IPHONE
|
||||
// TOXAUDIO: -incoming-audio-
|
||||
self.outputQueue = [[OCTAudioQueue alloc] initWithOutputDeviceID:nil error:error];
|
||||
// TOXAUDIO: -outgoing-audio-
|
||||
self.inputQueue = [[OCTAudioQueue alloc] initWithInputDeviceID:nil error:error];
|
||||
#else
|
||||
self.outputQueue = [[OCTAudioQueue alloc] initWithOutputDeviceID:self.outputDeviceID error:error];
|
||||
self.inputQueue = [[OCTAudioQueue alloc] initWithInputDeviceID:self.inputDeviceID error:error];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,74 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "TPCircularBuffer.h"
|
||||
|
||||
@import AudioToolbox;
|
||||
|
||||
#pragma mark - C declarations
|
||||
|
||||
extern OSStatus (*_AudioQueueAllocateBuffer)(AudioQueueRef inAQ,
|
||||
UInt32 inBufferByteSize,
|
||||
AudioQueueBufferRef *outBuffer);
|
||||
extern OSStatus (*_AudioQueueDispose)(AudioQueueRef inAQ,
|
||||
Boolean inImmediate);
|
||||
extern OSStatus (*_AudioQueueEnqueueBuffer)(AudioQueueRef inAQ,
|
||||
AudioQueueBufferRef inBuffer,
|
||||
UInt32 inNumPacketDescs,
|
||||
const AudioStreamPacketDescription *inPacketDescs);
|
||||
extern OSStatus (*_AudioQueueFreeBuffer)(AudioQueueRef inAQ,
|
||||
AudioQueueBufferRef inBuffer);
|
||||
extern OSStatus (*_AudioQueueNewInput)(const AudioStreamBasicDescription *inFormat,
|
||||
AudioQueueInputCallback inCallbackProc,
|
||||
void *inUserData,
|
||||
CFRunLoopRef inCallbackRunLoop,
|
||||
CFStringRef inCallbackRunLoopMode,
|
||||
UInt32 inFlags,
|
||||
AudioQueueRef *outAQ);
|
||||
extern OSStatus (*_AudioQueueNewOutput)(const AudioStreamBasicDescription *inFormat,
|
||||
AudioQueueOutputCallback inCallbackProc,
|
||||
void *inUserData,
|
||||
CFRunLoopRef inCallbackRunLoop,
|
||||
CFStringRef inCallbackRunLoopMode,
|
||||
UInt32 inFlags,
|
||||
AudioQueueRef *outAQ);
|
||||
extern OSStatus (*_AudioQueueSetProperty)(AudioQueueRef inAQ,
|
||||
AudioQueuePropertyID inID,
|
||||
const void *inData,
|
||||
UInt32 inDataSize);
|
||||
extern OSStatus (*_AudioQueueStart)(AudioQueueRef inAQ,
|
||||
const AudioTimeStamp *inStartTime);
|
||||
extern OSStatus (*_AudioQueueStop)(AudioQueueRef inAQ,
|
||||
Boolean inImmediate);
|
||||
#if ! TARGET_OS_IPHONE
|
||||
extern OSStatus (*_AudioObjectGetPropertyData)(AudioObjectID inObjectID,
|
||||
const AudioObjectPropertyAddress *inAddress,
|
||||
UInt32 inQualifierDataSize,
|
||||
const void *inQualifierData,
|
||||
UInt32 *ioDataSize,
|
||||
void *outData);
|
||||
#endif
|
||||
|
||||
/* no idea what to name this thing, so here it is */
|
||||
@interface OCTAudioQueue : NSObject
|
||||
|
||||
@property (strong, nonatomic, readonly) NSString *deviceID;
|
||||
@property (copy, nonatomic) void (^sendDataBlock)(void *, OCTToxAVSampleCount, OCTToxAVSampleRate, OCTToxAVChannels);
|
||||
@property (assign, nonatomic, readonly) BOOL running;
|
||||
|
||||
- (instancetype)initWithInputDeviceID:(NSString *)devID error:(NSError **)error;
|
||||
- (instancetype)initWithOutputDeviceID:(NSString *)devID error:(NSError **)error;
|
||||
|
||||
- (TPCircularBuffer *)getBufferPointer;
|
||||
- (BOOL)updateSampleRate:(OCTToxAVSampleRate)sampleRate numberOfChannels:(OCTToxAVChannels)numberOfChannels error:(NSError **)err;
|
||||
|
||||
#if ! TARGET_OS_IPHONE
|
||||
- (BOOL)setDeviceID:(NSString *)deviceID error:(NSError **)err;
|
||||
#endif
|
||||
|
||||
- (BOOL)begin:(NSError **)error;
|
||||
- (BOOL)stop:(NSError **)error;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,425 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTToxAV.h"
|
||||
#import "OCTAudioQueue.h"
|
||||
#import "TPCircularBuffer.h"
|
||||
#import "OCTLogging.h"
|
||||
|
||||
@import AVFoundation;
|
||||
@import AudioToolbox;
|
||||
|
||||
const int kBufferLength = 384000;
|
||||
const int kNumberOfChannels = 1;
|
||||
const int kDefaultSampleRate = 48000;
|
||||
const int kSampleCount_incoming_audio = 1920;
|
||||
const int kSampleCount_outgoing_audio = (1920 / 2);
|
||||
const int kBitsPerByte = 8;
|
||||
const int kFramesPerPacket = 1;
|
||||
// if you make this too small, the output queue will silently not play,
|
||||
// but you will still get fill callbacks; it's really weird
|
||||
const int kFramesPerOutputBuffer_incoming_audio = kSampleCount_incoming_audio / 4;
|
||||
const int kFramesPerOutputBuffer_outgoing_audio = kSampleCount_outgoing_audio / 4;
|
||||
const int kBytesPerSample = sizeof(SInt16);
|
||||
const int kNumberOfAudioQueueBuffers = 8;
|
||||
|
||||
OSStatus (*_AudioQueueAllocateBuffer)(AudioQueueRef inAQ,
|
||||
UInt32 inBufferByteSize,
|
||||
AudioQueueBufferRef *outBuffer) = AudioQueueAllocateBuffer;
|
||||
OSStatus (*_AudioQueueDispose)(AudioQueueRef inAQ,
|
||||
Boolean inImmediate) = AudioQueueDispose;
|
||||
OSStatus (*_AudioQueueEnqueueBuffer)(AudioQueueRef inAQ,
|
||||
AudioQueueBufferRef inBuffer,
|
||||
UInt32 inNumPacketDescs,
|
||||
const AudioStreamPacketDescription *inPacketDescs) = AudioQueueEnqueueBuffer;
|
||||
OSStatus (*_AudioQueueFreeBuffer)(AudioQueueRef inAQ,
|
||||
AudioQueueBufferRef inBuffer) = AudioQueueFreeBuffer;
|
||||
OSStatus (*_AudioQueueNewInput)(const AudioStreamBasicDescription *inFormat,
|
||||
AudioQueueInputCallback inCallbackProc,
|
||||
void *inUserData,
|
||||
CFRunLoopRef inCallbackRunLoop,
|
||||
CFStringRef inCallbackRunLoopMode,
|
||||
UInt32 inFlags,
|
||||
AudioQueueRef *outAQ) = AudioQueueNewInput;
|
||||
OSStatus (*_AudioQueueNewOutput)(const AudioStreamBasicDescription *inFormat,
|
||||
AudioQueueOutputCallback inCallbackProc,
|
||||
void *inUserData,
|
||||
CFRunLoopRef inCallbackRunLoop,
|
||||
CFStringRef inCallbackRunLoopMode,
|
||||
UInt32 inFlags,
|
||||
AudioQueueRef *outAQ) = AudioQueueNewOutput;
|
||||
OSStatus (*_AudioQueueSetProperty)(AudioQueueRef inAQ,
|
||||
AudioQueuePropertyID inID,
|
||||
const void *inData,
|
||||
UInt32 inDataSize) = AudioQueueSetProperty;
|
||||
OSStatus (*_AudioQueueStart)(AudioQueueRef inAQ,
|
||||
const AudioTimeStamp *inStartTime) = AudioQueueStart;
|
||||
OSStatus (*_AudioQueueStop)(AudioQueueRef inAQ,
|
||||
Boolean inImmediate) = AudioQueueStop;
|
||||
#if ! TARGET_OS_IPHONE
|
||||
OSStatus (*_AudioObjectGetPropertyData)(AudioObjectID inObjectID,
|
||||
const AudioObjectPropertyAddress *inAddress,
|
||||
UInt32 inQualifierDataSize,
|
||||
const void *inQualifierData,
|
||||
UInt32 *ioDataSize,
|
||||
void *outData) = AudioObjectGetPropertyData;
|
||||
#endif
|
||||
|
||||
static NSError *OCTErrorFromCoreAudioCode(OSStatus resultCode)
|
||||
{
|
||||
return [NSError errorWithDomain:NSOSStatusErrorDomain
|
||||
code:resultCode
|
||||
userInfo:@{NSLocalizedDescriptionKey : @"Consult the CoreAudio header files/google for the meaning of the error code."}];
|
||||
}
|
||||
|
||||
#if ! TARGET_OS_IPHONE
|
||||
static NSString *OCTGetSystemAudioDevice(AudioObjectPropertySelector sel, NSError **err)
|
||||
{
|
||||
AudioDeviceID devID = 0;
|
||||
OSStatus ok = 0;
|
||||
UInt32 size = sizeof(AudioDeviceID);
|
||||
AudioObjectPropertyAddress address = {
|
||||
.mSelector = sel,
|
||||
.mScope = kAudioObjectPropertyScopeGlobal,
|
||||
.mElement = kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
ok = _AudioObjectGetPropertyData(kAudioObjectSystemObject, &address, 0, NULL, &size, &devID);
|
||||
if (ok != kAudioHardwareNoError) {
|
||||
OCTLogCCError(@"failed AudioObjectGetPropertyData for system object: %d! Crash may or may not be imminent", ok);
|
||||
if (err) {
|
||||
*err = OCTErrorFromCoreAudioCode(ok);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
address.mSelector = kAudioDevicePropertyDeviceUID;
|
||||
CFStringRef unique = NULL;
|
||||
size = sizeof(unique);
|
||||
ok = _AudioObjectGetPropertyData(devID, &address, 0, NULL, &size, &unique);
|
||||
if (ok != kAudioHardwareNoError) {
|
||||
OCTLogCCError(@"failed AudioObjectGetPropertyData for selected device: %d! Crash may or may not be imminent", ok);
|
||||
if (err) {
|
||||
*err = OCTErrorFromCoreAudioCode(ok);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
return (__bridge NSString *)unique;
|
||||
}
|
||||
#endif
|
||||
|
||||
@interface OCTAudioQueue ()
|
||||
|
||||
// use this to track what nil means in terms of audio device
|
||||
@property (assign, nonatomic) BOOL isOutput;
|
||||
@property (assign, nonatomic) AudioStreamBasicDescription streamFmt;
|
||||
@property (assign, nonatomic) AudioQueueRef audioQueue;
|
||||
@property (assign, nonatomic) TPCircularBuffer buffer;
|
||||
@property (assign, nonatomic) BOOL running;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTAudioQueue
|
||||
{
|
||||
AudioQueueBufferRef _AQBuffers[kNumberOfAudioQueueBuffers];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDeviceID:(NSString *)devID isOutput:(BOOL)output error:(NSError **)error
|
||||
{
|
||||
#if TARGET_OS_IPHONE
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
_streamFmt.mSampleRate = session.sampleRate;
|
||||
#else
|
||||
_streamFmt.mSampleRate = kDefaultSampleRate;
|
||||
#endif
|
||||
_streamFmt.mFormatID = kAudioFormatLinearPCM;
|
||||
_streamFmt.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
|
||||
_streamFmt.mChannelsPerFrame = kNumberOfChannels;
|
||||
_streamFmt.mBytesPerFrame = kBytesPerSample * kNumberOfChannels;
|
||||
_streamFmt.mBitsPerChannel = kBitsPerByte * kBytesPerSample;
|
||||
_streamFmt.mFramesPerPacket = kFramesPerPacket;
|
||||
_streamFmt.mBytesPerPacket = kBytesPerSample * kNumberOfChannels * kFramesPerPacket;
|
||||
_isOutput = output;
|
||||
_deviceID = devID;
|
||||
|
||||
TPCircularBufferInit(&_buffer, kBufferLength);
|
||||
OSStatus res = [self createAudioQueue];
|
||||
if (res != 0) {
|
||||
if (error) {
|
||||
*error = OCTErrorFromCoreAudioCode(res);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (instancetype)initWithInputDeviceID:(NSString *)devID error:(NSError **)error
|
||||
{
|
||||
// TOXAUDIO: -outgoing-audio-
|
||||
return [self initWithDeviceID:devID isOutput:NO error:error];
|
||||
}
|
||||
|
||||
- (instancetype)initWithOutputDeviceID:(NSString *)devID error:(NSError **)error
|
||||
{
|
||||
// TOXAUDIO: -incoming-audio-
|
||||
return [self initWithDeviceID:devID isOutput:YES error:error];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (self.running) {
|
||||
[self stop:nil];
|
||||
}
|
||||
|
||||
if (self.audioQueue) {
|
||||
_AudioQueueDispose(self.audioQueue, true);
|
||||
}
|
||||
|
||||
TPCircularBufferCleanup(&_buffer);
|
||||
}
|
||||
|
||||
- (OSStatus)createAudioQueue
|
||||
{
|
||||
OSStatus err;
|
||||
if (self.isOutput) {
|
||||
// TOXAUDIO: -incoming-audio-
|
||||
err = _AudioQueueNewOutput(&_streamFmt, (void *)&FillOutputBuffer, (__bridge void *)self, NULL, kCFRunLoopCommonModes, 0, &_audioQueue);
|
||||
}
|
||||
else {
|
||||
// TOXAUDIO: -outgoing-audio-
|
||||
err = _AudioQueueNewInput(&_streamFmt, (void *)&InputAvailable, (__bridge void *)self, NULL, kCFRunLoopCommonModes, 0, &_audioQueue);
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (_deviceID) {
|
||||
err = _AudioQueueSetProperty(self.audioQueue, kAudioQueueProperty_CurrentDevice, &_deviceID, sizeof(CFStringRef));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
- (BOOL)begin:(NSError **)error
|
||||
{
|
||||
OCTLogVerbose(@"begin");
|
||||
|
||||
if (! self.audioQueue) {
|
||||
OSStatus res = [self createAudioQueue];
|
||||
if (res != 0) {
|
||||
OCTLogError(@"Can't create the audio queue again after a presumably failed updateSampleRate:... call.");
|
||||
if (error) {
|
||||
*error = OCTErrorFromCoreAudioCode(res);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumberOfAudioQueueBuffers; ++i) {
|
||||
if (self.isOutput) {
|
||||
// TOXAUDIO: -incoming-audio-
|
||||
_AudioQueueAllocateBuffer(self.audioQueue, kBytesPerSample * kNumberOfChannels * kFramesPerOutputBuffer_incoming_audio, &(_AQBuffers[i]));
|
||||
} else {
|
||||
// TOXAUDIO: -outgoing-audio-
|
||||
_AudioQueueAllocateBuffer(self.audioQueue, kBytesPerSample * kNumberOfChannels * kFramesPerOutputBuffer_outgoing_audio, &(_AQBuffers[i]));
|
||||
}
|
||||
_AudioQueueEnqueueBuffer(self.audioQueue, _AQBuffers[i], 0, NULL);
|
||||
if (self.isOutput) {
|
||||
// TOXAUDIO: -outgoing-audio-
|
||||
// For some reason we have to fill it with zero or the callback never gets called.
|
||||
FillOutputBuffer(self, self.audioQueue, _AQBuffers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
OCTLogVerbose(@"Allocated buffers; starting now!");
|
||||
OSStatus res = _AudioQueueStart(self.audioQueue, NULL);
|
||||
if (res != 0) {
|
||||
if (error) {
|
||||
*error = OCTErrorFromCoreAudioCode(res);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
self.running = YES;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)stop:(NSError **)error
|
||||
{
|
||||
OCTLogVerbose(@"stop");
|
||||
OSStatus res = _AudioQueueStop(self.audioQueue, true);
|
||||
if (res != 0) {
|
||||
if (error) {
|
||||
*error = OCTErrorFromCoreAudioCode(res);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumberOfAudioQueueBuffers; ++i) {
|
||||
_AudioQueueFreeBuffer(self.audioQueue, _AQBuffers[i]);
|
||||
}
|
||||
|
||||
OCTLogVerbose(@"Freed buffers");
|
||||
self.running = NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (TPCircularBuffer *)getBufferPointer
|
||||
{
|
||||
return &_buffer;
|
||||
}
|
||||
|
||||
- (BOOL)setDeviceID:(NSString *)deviceID error:(NSError **)err
|
||||
{
|
||||
#if ! TARGET_OS_IPHONE
|
||||
if (deviceID == nil) {
|
||||
OCTLogVerbose(@"using the default device because nil passed to OCTAudioQueue setDeviceID:");
|
||||
deviceID = OCTGetSystemAudioDevice(self.isOutput ?
|
||||
kAudioHardwarePropertyDefaultOutputDevice :
|
||||
kAudioHardwarePropertyDefaultInputDevice, err);
|
||||
if (! deviceID) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL needToRestart = self.running;
|
||||
|
||||
// we need to pause the queue for a sec
|
||||
if (needToRestart && ! [self stop:err]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
OSStatus ok = _AudioQueueSetProperty(self.audioQueue, kAudioQueueProperty_CurrentDevice, &deviceID, sizeof(CFStringRef));
|
||||
|
||||
if (ok != 0) {
|
||||
OCTLogError(@"setDeviceID: Error while live setting device to '%@': %d", deviceID, ok);
|
||||
if (err) {
|
||||
*err = OCTErrorFromCoreAudioCode(ok);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_deviceID = deviceID;
|
||||
OCTLogVerbose(@"Successfully set the device id to %@", deviceID);
|
||||
}
|
||||
|
||||
if ((needToRestart && ! [self begin:err]) || (ok != 0)) {
|
||||
return NO;
|
||||
}
|
||||
else {
|
||||
return YES;
|
||||
}
|
||||
#else
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (BOOL)updateSampleRate:(OCTToxAVSampleRate)sampleRate numberOfChannels:(OCTToxAVChannels)numberOfChannels error:(NSError **)err
|
||||
{
|
||||
OCTLogVerbose(@"updateSampleRate %u, %u", sampleRate, (unsigned int)numberOfChannels);
|
||||
|
||||
BOOL needToRestart = self.running;
|
||||
|
||||
if (needToRestart && ! [self stop:err]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
AudioQueueRef aq = self.audioQueue;
|
||||
self.audioQueue = nil;
|
||||
_AudioQueueDispose(aq, true);
|
||||
|
||||
_streamFmt.mSampleRate = sampleRate;
|
||||
_streamFmt.mChannelsPerFrame = numberOfChannels;
|
||||
_streamFmt.mBytesPerFrame = kBytesPerSample * numberOfChannels;
|
||||
_streamFmt.mBytesPerPacket = kBytesPerSample * numberOfChannels * kFramesPerPacket;
|
||||
|
||||
OSStatus res = [self createAudioQueue];
|
||||
if (res != 0) {
|
||||
OCTLogError(@"oops, could not recreate the audio queue: %d after samplerate/nc change. enjoy your overflowing buffer", (int)res);
|
||||
if (err) {
|
||||
*err = OCTErrorFromCoreAudioCode(res);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
else if (needToRestart) {
|
||||
return [self begin:err];
|
||||
}
|
||||
else {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
// avoid annoying bridge cast in 1st param!
|
||||
static void InputAvailable(OCTAudioQueue *__unsafe_unretained context,
|
||||
AudioQueueRef inAQ,
|
||||
AudioQueueBufferRef inBuffer,
|
||||
const AudioTimeStamp *inStartTime,
|
||||
UInt32 inNumPackets,
|
||||
const AudioStreamPacketDescription *inPacketDesc)
|
||||
{
|
||||
TPCircularBufferProduceBytes(&(context->_buffer),
|
||||
inBuffer->mAudioData,
|
||||
inBuffer->mAudioDataByteSize);
|
||||
|
||||
int32_t availableBytesToConsume;
|
||||
void *tail = TPCircularBufferTail(&context->_buffer, &availableBytesToConsume);
|
||||
|
||||
// TOXAUDIO: -outgoing-audio-
|
||||
int32_t minimalBytesToConsume = kSampleCount_outgoing_audio * kNumberOfChannels * sizeof(SInt16);
|
||||
|
||||
if (context.isOutput) {
|
||||
// TOXAUDIO: -incoming-audio-
|
||||
minimalBytesToConsume = kSampleCount_incoming_audio * kNumberOfChannels * sizeof(SInt16);
|
||||
}
|
||||
|
||||
int32_t cyclesToConsume = availableBytesToConsume / minimalBytesToConsume;
|
||||
|
||||
for (int32_t i = 0; i < cyclesToConsume; i++) {
|
||||
if (context.isOutput) {
|
||||
// TOXAUDIO: -incoming-audio-
|
||||
context.sendDataBlock(tail, kSampleCount_incoming_audio, context.streamFmt.mSampleRate, kNumberOfChannels);
|
||||
} else {
|
||||
// TOXAUDIO: -outgoing-audio-
|
||||
context.sendDataBlock(tail, kSampleCount_outgoing_audio, context.streamFmt.mSampleRate, kNumberOfChannels);
|
||||
}
|
||||
TPCircularBufferConsume(&context->_buffer, minimalBytesToConsume);
|
||||
tail = TPCircularBufferTail(&context->_buffer, &availableBytesToConsume);
|
||||
}
|
||||
|
||||
_AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
|
||||
}
|
||||
|
||||
static void FillOutputBuffer(OCTAudioQueue *__unsafe_unretained context,
|
||||
AudioQueueRef inAQ,
|
||||
AudioQueueBufferRef inBuffer)
|
||||
{
|
||||
int32_t targetBufferSize = inBuffer->mAudioDataBytesCapacity;
|
||||
SInt16 *targetBuffer = inBuffer->mAudioData;
|
||||
|
||||
int32_t availableBytes;
|
||||
SInt16 *buffer = TPCircularBufferTail(&context->_buffer, &availableBytes);
|
||||
|
||||
if (buffer) {
|
||||
uint32_t cpy = MIN(availableBytes, targetBufferSize);
|
||||
memcpy(targetBuffer, buffer, cpy);
|
||||
TPCircularBufferConsume(&context->_buffer, cpy);
|
||||
|
||||
if (cpy != targetBufferSize) {
|
||||
memset(targetBuffer + cpy, 0, targetBufferSize - cpy);
|
||||
OCTLogCCWarn(@"warning not enough frames!!!");
|
||||
}
|
||||
inBuffer->mAudioDataByteSize = targetBufferSize;
|
||||
}
|
||||
else {
|
||||
memset(targetBuffer, 0, targetBufferSize);
|
||||
inBuffer->mAudioDataByteSize = targetBufferSize;
|
||||
}
|
||||
|
||||
_AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,77 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTDefaultFileStorage.h"
|
||||
|
||||
@interface OCTDefaultFileStorage ()
|
||||
|
||||
@property (copy, nonatomic) NSString *saveFileName;
|
||||
@property (copy, nonatomic) NSString *baseDirectory;
|
||||
@property (copy, nonatomic) NSString *temporaryDirectory;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTDefaultFileStorage
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (instancetype)initWithBaseDirectory:(NSString *)baseDirectory temporaryDirectory:(NSString *)temporaryDirectory
|
||||
{
|
||||
return [self initWithToxSaveFileName:nil baseDirectory:baseDirectory temporaryDirectory:temporaryDirectory];
|
||||
}
|
||||
|
||||
- (instancetype)initWithToxSaveFileName:(NSString *)saveFileName
|
||||
baseDirectory:(NSString *)baseDirectory
|
||||
temporaryDirectory:(NSString *)temporaryDirectory
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (! saveFileName) {
|
||||
saveFileName = @"save";
|
||||
}
|
||||
|
||||
self.saveFileName = [saveFileName stringByAppendingString:@".tox"];
|
||||
self.baseDirectory = baseDirectory;
|
||||
self.temporaryDirectory = temporaryDirectory;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - OCTFileStorageProtocol
|
||||
|
||||
- (NSString *)pathForToxSaveFile
|
||||
{
|
||||
return [self.baseDirectory stringByAppendingPathComponent:self.saveFileName];
|
||||
}
|
||||
|
||||
- (NSString *)pathForDatabase
|
||||
{
|
||||
return [self.baseDirectory stringByAppendingPathComponent:@"database"];
|
||||
}
|
||||
|
||||
- (NSString *)pathForDatabaseEncryptionKey
|
||||
{
|
||||
return [self.baseDirectory stringByAppendingPathComponent:@"database.encryptionkey"];
|
||||
}
|
||||
|
||||
- (NSString *)pathForDownloadedFilesDirectory
|
||||
{
|
||||
return [self.baseDirectory stringByAppendingPathComponent:@"files"];
|
||||
}
|
||||
|
||||
- (NSString *)pathForUploadedFilesDirectory
|
||||
{
|
||||
return [self.baseDirectory stringByAppendingPathComponent:@"files"];
|
||||
}
|
||||
|
||||
- (NSString *)pathForTemporaryFilesDirectory
|
||||
{
|
||||
return self.temporaryDirectory;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,51 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTManagerConfiguration.h"
|
||||
#import "OCTDefaultFileStorage.h"
|
||||
|
||||
static NSString *const kDefaultBaseDirectory = @"me.dvor.objcTox";
|
||||
|
||||
@implementation OCTManagerConfiguration
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (instancetype)defaultConfiguration
|
||||
{
|
||||
OCTManagerConfiguration *configuration = [OCTManagerConfiguration new];
|
||||
|
||||
NSString *baseDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
|
||||
baseDirectory = [baseDirectory stringByAppendingPathComponent:kDefaultBaseDirectory];
|
||||
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:baseDirectory
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:nil];
|
||||
|
||||
configuration.fileStorage = [[OCTDefaultFileStorage alloc] initWithBaseDirectory:baseDirectory
|
||||
temporaryDirectory:NSTemporaryDirectory()];
|
||||
|
||||
configuration.options = [OCTToxOptions new];
|
||||
|
||||
configuration.importToxSaveFromPath = nil;
|
||||
configuration.useFauxOfflineMessaging = YES;
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
OCTManagerConfiguration *configuration = [[[self class] allocWithZone:zone] init];
|
||||
|
||||
configuration.fileStorage = self.fileStorage;
|
||||
configuration.options = [self.options copy];
|
||||
configuration.importToxSaveFromPath = [self.importToxSaveFromPath copy];
|
||||
configuration.useFauxOfflineMessaging = self.useFauxOfflineMessaging;
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,112 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "OCTToxConstants.h"
|
||||
#import "OCTManagerConstants.h"
|
||||
|
||||
@class OCTObject;
|
||||
@class OCTFriend;
|
||||
@class OCTChat;
|
||||
@class OCTCall;
|
||||
@class OCTMessageAbstract;
|
||||
@class OCTSettingsStorageObject;
|
||||
@class RLMResults;
|
||||
|
||||
@interface OCTRealmManager : NSObject
|
||||
|
||||
/**
|
||||
* Storage with all objcTox settings.
|
||||
*/
|
||||
@property (strong, nonatomic, readonly) OCTSettingsStorageObject *settingsStorage;
|
||||
|
||||
/**
|
||||
* Migrate unencrypted database to encrypted one.
|
||||
*
|
||||
* @param databasePath Path to unencrypted database.
|
||||
* @param encryptionKey Key used to encrypt database.
|
||||
* @param error Error parameter will be filled in case of failure. It will contain RLMRealm or NSFileManager error.
|
||||
*
|
||||
* @return YES on success, NO on failure.
|
||||
*/
|
||||
+ (BOOL)migrateToEncryptedDatabase:(NSString *)databasePath
|
||||
encryptionKey:(NSData *)encryptionKey
|
||||
error:(NSError **)error;
|
||||
|
||||
/**
|
||||
* Create RealmManager.
|
||||
*
|
||||
* @param fileURL path to Realm file. File will be created if it doesn't exist.
|
||||
* @param encryptionKey A 64-byte key to use to encrypt the data, or nil if encryption is not enabled.
|
||||
*/
|
||||
- (instancetype)initWithDatabaseFileURL:(NSURL *)fileURL encryptionKey:(NSData *)encryptionKey;
|
||||
|
||||
- (NSURL *)realmFileURL;
|
||||
|
||||
#pragma mark - Basic methods
|
||||
|
||||
- (id)objectWithUniqueIdentifier:(NSString *)uniqueIdentifier class:(Class)class;
|
||||
|
||||
- (RLMResults *)objectsWithClass:(Class)class predicate:(NSPredicate *)predicate;
|
||||
|
||||
- (void)addObject:(OCTObject *)object;
|
||||
- (void)deleteObject:(OCTObject *)object;
|
||||
|
||||
/*
|
||||
* All realm objects should be updated ONLY using following two methods.
|
||||
*
|
||||
* Specified object will be passed in block.
|
||||
*/
|
||||
- (void)updateObject:(OCTObject *)object withBlock:(void (^)(id theObject))updateBlock;
|
||||
|
||||
- (void)updateObjectsWithClass:(Class)class
|
||||
predicate:(NSPredicate *)predicate
|
||||
updateBlock:(void (^)(id theObject))updateBlock;
|
||||
|
||||
#pragma mark - Other methods
|
||||
|
||||
- (OCTFriend *)friendWithPublicKey:(NSString *)publicKey;
|
||||
- (OCTChat *)getOrCreateChatWithFriend:(OCTFriend *)friend;
|
||||
- (OCTCall *)createCallWithChat:(OCTChat *)chat status:(OCTCallStatus)status;
|
||||
|
||||
/**
|
||||
* Gets the current call for the chat if and only if it exists.
|
||||
* This will not create a call object.
|
||||
* @param chat The chat that is related to the call.
|
||||
* @return A call object if it exists, nil if no call is session for this call.
|
||||
*/
|
||||
- (OCTCall *)getCurrentCallForChat:(OCTChat *)chat;
|
||||
|
||||
- (void)removeMessages:(NSArray<OCTMessageAbstract *> *)messages;
|
||||
- (void)removeAllMessagesInChat:(OCTChat *)chat removeChat:(BOOL)removeChat;
|
||||
|
||||
/**
|
||||
* Converts all the OCTCalls to OCTMessageCalls.
|
||||
* Only use this when first starting the app or during termination.
|
||||
*/
|
||||
- (void)convertAllCallsToMessages;
|
||||
|
||||
- (OCTMessageAbstract *)addMessageWithText:(NSString *)text
|
||||
type:(OCTToxMessageType)type
|
||||
chat:(OCTChat *)chat
|
||||
sender:(OCTFriend *)sender
|
||||
messageId:(OCTToxMessageId)messageId
|
||||
msgv3HashHex:(NSString *)msgv3HashHex
|
||||
sentPush:(BOOL)sentPush
|
||||
tssent:(UInt32)tssent
|
||||
tsrcvd:(UInt32)tsrcvd;
|
||||
|
||||
- (OCTMessageAbstract *)addMessageWithFileNumber:(OCTToxFileNumber)fileNumber
|
||||
fileType:(OCTMessageFileType)fileType
|
||||
fileSize:(OCTToxFileSize)fileSize
|
||||
fileName:(NSString *)fileName
|
||||
filePath:(NSString *)filePath
|
||||
fileUTI:(NSString *)fileUTI
|
||||
chat:(OCTChat *)chat
|
||||
sender:(OCTFriend *)sender;
|
||||
|
||||
- (OCTMessageAbstract *)addMessageCall:(OCTCall *)call;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,665 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Realm/Realm.h>
|
||||
|
||||
#import "OCTRealmManager.h"
|
||||
#import "OCTFriend.h"
|
||||
#import "OCTFriendRequest.h"
|
||||
#import "OCTChat.h"
|
||||
#import "OCTCall.h"
|
||||
#import "OCTMessageAbstract.h"
|
||||
#import "OCTMessageText.h"
|
||||
#import "OCTMessageFile.h"
|
||||
#import "OCTMessageCall.h"
|
||||
#import "OCTSettingsStorageObject.h"
|
||||
#import "OCTLogging.h"
|
||||
|
||||
static const uint64_t kCurrentSchemeVersion = 16;
|
||||
static NSString *kSettingsStorageObjectPrimaryKey = @"kSettingsStorageObjectPrimaryKey";
|
||||
|
||||
@interface OCTRealmManager ()
|
||||
|
||||
@property (strong, nonatomic) dispatch_queue_t queue;
|
||||
@property (strong, nonatomic) RLMRealm *realm;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTRealmManager
|
||||
@synthesize settingsStorage = _settingsStorage;
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (BOOL)migrateToEncryptedDatabase:(NSString *)databasePath
|
||||
encryptionKey:(NSData *)encryptionKey
|
||||
error:(NSError **)error
|
||||
{
|
||||
NSString *tempPath = [databasePath stringByAppendingPathExtension:@"tmp"];
|
||||
|
||||
@autoreleasepool {
|
||||
RLMRealm *old = [OCTRealmManager createRealmWithFileURL:[NSURL fileURLWithPath:databasePath]
|
||||
encryptionKey:nil
|
||||
error:error];
|
||||
|
||||
if (! old) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (! [old writeCopyToURL:[NSURL fileURLWithPath:tempPath] encryptionKey:encryptionKey error:error]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
if (! [[NSFileManager defaultManager] removeItemAtPath:databasePath error:error]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (! [[NSFileManager defaultManager] moveItemAtPath:tempPath toPath:databasePath error:error]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (instancetype)initWithDatabaseFileURL:(NSURL *)fileURL encryptionKey:(NSData *)encryptionKey
|
||||
{
|
||||
NSParameterAssert(fileURL);
|
||||
|
||||
self = [super init];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
OCTLogInfo(@"init with fileURL %@", fileURL);
|
||||
|
||||
_queue = dispatch_queue_create("OCTRealmManager queue", NULL);
|
||||
|
||||
__weak OCTRealmManager *weakSelf = self;
|
||||
dispatch_sync(_queue, ^{
|
||||
__strong OCTRealmManager *strongSelf = weakSelf;
|
||||
|
||||
// TODO handle error
|
||||
self->_realm = [OCTRealmManager createRealmWithFileURL:fileURL encryptionKey:encryptionKey error:nil];
|
||||
[strongSelf createSettingsStorage];
|
||||
});
|
||||
|
||||
[self convertAllCallsToMessages];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (NSURL *)realmFileURL
|
||||
{
|
||||
return self.realm.configuration.fileURL;
|
||||
}
|
||||
|
||||
#pragma mark - Basic methods
|
||||
|
||||
- (id)objectWithUniqueIdentifier:(NSString *)uniqueIdentifier class:(Class)class
|
||||
{
|
||||
NSParameterAssert(uniqueIdentifier);
|
||||
NSParameterAssert(class);
|
||||
|
||||
__block OCTObject *object = nil;
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
object = [class objectInRealm:self.realm forPrimaryKey:uniqueIdentifier];
|
||||
});
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
- (RLMResults *)objectsWithClass:(Class)class predicate:(NSPredicate *)predicate
|
||||
{
|
||||
NSParameterAssert(class);
|
||||
|
||||
__block RLMResults *results;
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
results = [class objectsInRealm:self.realm withPredicate:predicate];
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
- (void)updateObject:(OCTObject *)object withBlock:(void (^)(id theObject))updateBlock
|
||||
{
|
||||
NSParameterAssert(object);
|
||||
NSParameterAssert(updateBlock);
|
||||
|
||||
// OCTLogInfo(@"updateObject %@", object);
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
[self.realm beginWriteTransaction];
|
||||
|
||||
updateBlock(object);
|
||||
|
||||
[self.realm commitWriteTransaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)updateObjectsWithClass:(Class)class
|
||||
predicate:(NSPredicate *)predicate
|
||||
updateBlock:(void (^)(id theObject))updateBlock
|
||||
{
|
||||
NSParameterAssert(class);
|
||||
NSParameterAssert(updateBlock);
|
||||
|
||||
// OCTLogInfo(@"updating objects of class %@ with predicate %@", NSStringFromClass(class), predicate);
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
RLMResults *results = [class objectsInRealm:self.realm withPredicate:predicate];
|
||||
|
||||
[self.realm beginWriteTransaction];
|
||||
for (id object in results) {
|
||||
updateBlock(object);
|
||||
}
|
||||
[self.realm commitWriteTransaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)addObject:(OCTObject *)object
|
||||
{
|
||||
NSParameterAssert(object);
|
||||
|
||||
// OCTLogInfo(@"add object %@", object);
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
[self.realm beginWriteTransaction];
|
||||
|
||||
[self.realm addObject:object];
|
||||
|
||||
[self.realm commitWriteTransaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)deleteObject:(OCTObject *)object
|
||||
{
|
||||
NSParameterAssert(object);
|
||||
|
||||
// OCTLogInfo(@"delete object %@", object);
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
[self.realm beginWriteTransaction];
|
||||
|
||||
[self.realm deleteObject:object];
|
||||
|
||||
[self.realm commitWriteTransaction];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Other methods
|
||||
|
||||
+ (RLMRealm *)createRealmWithFileURL:(NSURL *)fileURL encryptionKey:(NSData *)encryptionKey error:(NSError **)error
|
||||
{
|
||||
RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
|
||||
configuration.fileURL = fileURL;
|
||||
configuration.schemaVersion = kCurrentSchemeVersion;
|
||||
configuration.migrationBlock = [self realmMigrationBlock];
|
||||
configuration.encryptionKey = encryptionKey;
|
||||
|
||||
RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration error:error];
|
||||
|
||||
if (! realm && error) {
|
||||
OCTLogInfo(@"Cannot create Realm, error %@", *error);
|
||||
}
|
||||
|
||||
return realm;
|
||||
}
|
||||
|
||||
- (void)createSettingsStorage
|
||||
{
|
||||
_settingsStorage = [OCTSettingsStorageObject objectInRealm:self.realm
|
||||
forPrimaryKey:kSettingsStorageObjectPrimaryKey];
|
||||
|
||||
if (! _settingsStorage) {
|
||||
OCTLogInfo(@"no _settingsStorage, creating it");
|
||||
_settingsStorage = [OCTSettingsStorageObject new];
|
||||
_settingsStorage.uniqueIdentifier = kSettingsStorageObjectPrimaryKey;
|
||||
|
||||
[self.realm beginWriteTransaction];
|
||||
[self.realm addObject:_settingsStorage];
|
||||
[self.realm commitWriteTransaction];
|
||||
}
|
||||
}
|
||||
|
||||
- (OCTFriend *)friendWithPublicKey:(NSString *)publicKey
|
||||
{
|
||||
NSAssert(publicKey, @"Public key should be non-empty.");
|
||||
__block OCTFriend *friend;
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
friend = [[OCTFriend objectsInRealm:self.realm where:@"publicKey == %@", publicKey] firstObject];
|
||||
});
|
||||
|
||||
return friend;
|
||||
}
|
||||
|
||||
- (OCTChat *)getOrCreateChatWithFriend:(OCTFriend *)friend
|
||||
{
|
||||
__block OCTChat *chat = nil;
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
// TODO add this (friends.@count == 1) condition. Currentry Realm doesn't support collection queries
|
||||
// See https://github.com/realm/realm-cocoa/issues/1490
|
||||
chat = [[OCTChat objectsInRealm:self.realm where:@"ANY friends == %@", friend] firstObject];
|
||||
|
||||
if (chat) {
|
||||
return;
|
||||
}
|
||||
|
||||
OCTLogInfo(@"creating chat with friend %@", friend);
|
||||
|
||||
chat = [OCTChat new];
|
||||
chat.lastActivityDateInterval = [[NSDate date] timeIntervalSince1970];
|
||||
|
||||
[self.realm beginWriteTransaction];
|
||||
|
||||
[self.realm addObject:chat];
|
||||
[chat.friends addObject:friend];
|
||||
|
||||
[self.realm commitWriteTransaction];
|
||||
});
|
||||
|
||||
return chat;
|
||||
}
|
||||
|
||||
- (OCTCall *)createCallWithChat:(OCTChat *)chat status:(OCTCallStatus)status
|
||||
{
|
||||
__block OCTCall *call = nil;
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
|
||||
call = [[OCTCall objectsInRealm:self.realm where:@"chat == %@", chat] firstObject];
|
||||
|
||||
if (call) {
|
||||
return;
|
||||
}
|
||||
|
||||
OCTLogInfo(@"creating call with chat %@", chat);
|
||||
|
||||
call = [OCTCall new];
|
||||
call.status = status;
|
||||
call.chat = chat;
|
||||
|
||||
[self.realm beginWriteTransaction];
|
||||
[self.realm addObject:call];
|
||||
[self.realm commitWriteTransaction];
|
||||
});
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
- (OCTCall *)getCurrentCallForChat:(OCTChat *)chat
|
||||
{
|
||||
__block OCTCall *call = nil;
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
|
||||
call = [[OCTCall objectsInRealm:self.realm where:@"chat == %@", chat] firstObject];
|
||||
});
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
- (void)removeMessages:(NSArray<OCTMessageAbstract *> *)messages
|
||||
{
|
||||
NSParameterAssert(messages);
|
||||
|
||||
OCTLogInfo(@"removing messages %lu", (unsigned long)messages.count);
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
[self.realm beginWriteTransaction];
|
||||
|
||||
NSMutableSet *changedChats = [NSMutableSet new];
|
||||
for (OCTMessageAbstract *message in messages) {
|
||||
[changedChats addObject:message.chatUniqueIdentifier];
|
||||
}
|
||||
|
||||
[self removeMessagesWithSubmessages:messages];
|
||||
|
||||
for (NSString *chatUniqueIdentifier in changedChats) {
|
||||
RLMResults *messages = [OCTMessageAbstract objectsInRealm:self.realm where:@"chatUniqueIdentifier == %@", chatUniqueIdentifier];
|
||||
messages = [messages sortedResultsUsingKeyPath:@"dateInterval" ascending:YES];
|
||||
|
||||
OCTChat *chat = [OCTChat objectInRealm:self.realm forPrimaryKey:chatUniqueIdentifier];
|
||||
chat.lastMessage = messages.lastObject;
|
||||
}
|
||||
|
||||
[self.realm commitWriteTransaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)removeAllMessagesInChat:(OCTChat *)chat removeChat:(BOOL)removeChat
|
||||
{
|
||||
NSParameterAssert(chat);
|
||||
|
||||
OCTLogInfo(@"removing chat with all messages %@", chat);
|
||||
|
||||
dispatch_sync(self.queue, ^{
|
||||
RLMResults *messages = [OCTMessageAbstract objectsInRealm:self.realm where:@"chatUniqueIdentifier == %@", chat.uniqueIdentifier];
|
||||
|
||||
[self.realm beginWriteTransaction];
|
||||
|
||||
[self removeMessagesWithSubmessages:messages];
|
||||
if (removeChat) {
|
||||
[self.realm deleteObject:chat];
|
||||
}
|
||||
|
||||
[self.realm commitWriteTransaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)convertAllCallsToMessages
|
||||
{
|
||||
RLMResults *calls = [OCTCall allObjectsInRealm:self.realm];
|
||||
|
||||
OCTLogInfo(@"removing %lu calls", (unsigned long)calls.count);
|
||||
|
||||
for (OCTCall *call in calls) {
|
||||
[self addMessageCall:call];
|
||||
}
|
||||
|
||||
[self.realm beginWriteTransaction];
|
||||
[self.realm deleteObjects:calls];
|
||||
[self.realm commitWriteTransaction];
|
||||
}
|
||||
|
||||
- (OCTMessageAbstract *)addMessageWithText:(NSString *)text
|
||||
type:(OCTToxMessageType)type
|
||||
chat:(OCTChat *)chat
|
||||
sender:(OCTFriend *)sender
|
||||
messageId:(OCTToxMessageId)messageId
|
||||
msgv3HashHex:(NSString *)msgv3HashHex
|
||||
sentPush:(BOOL)sentPush
|
||||
tssent:(UInt32)tssent
|
||||
tsrcvd:(UInt32)tsrcvd
|
||||
{
|
||||
NSParameterAssert(text);
|
||||
|
||||
OCTLogInfo(@"adding messageText to chat %@", chat);
|
||||
|
||||
OCTMessageText *messageText = [OCTMessageText new];
|
||||
messageText.text = text;
|
||||
messageText.isDelivered = NO;
|
||||
messageText.type = type;
|
||||
messageText.messageId = messageId;
|
||||
messageText.msgv3HashHex = msgv3HashHex;
|
||||
messageText.sentPush = sentPush;
|
||||
|
||||
return [self addMessageAbstractWithChat:chat sender:sender messageText:messageText messageFile:nil messageCall:nil tssent:tssent tsrcvd:tsrcvd];
|
||||
}
|
||||
|
||||
- (OCTMessageAbstract *)addMessageWithFileNumber:(OCTToxFileNumber)fileNumber
|
||||
fileType:(OCTMessageFileType)fileType
|
||||
fileSize:(OCTToxFileSize)fileSize
|
||||
fileName:(NSString *)fileName
|
||||
filePath:(NSString *)filePath
|
||||
fileUTI:(NSString *)fileUTI
|
||||
chat:(OCTChat *)chat
|
||||
sender:(OCTFriend *)sender
|
||||
{
|
||||
OCTLogInfo(@"adding messageFile to chat %@, fileSize %lld", chat, fileSize);
|
||||
|
||||
OCTMessageFile *messageFile = [OCTMessageFile new];
|
||||
messageFile.internalFileNumber = fileNumber;
|
||||
messageFile.fileType = fileType;
|
||||
messageFile.fileSize = fileSize;
|
||||
messageFile.fileName = fileName;
|
||||
[messageFile internalSetFilePath:filePath];
|
||||
messageFile.fileUTI = fileUTI;
|
||||
|
||||
return [self addMessageAbstractWithChat:chat sender:sender messageText:nil messageFile:messageFile messageCall:nil tssent:0 tsrcvd:0];
|
||||
}
|
||||
|
||||
- (OCTMessageAbstract *)addMessageCall:(OCTCall *)call
|
||||
{
|
||||
OCTLogInfo(@"adding messageCall to call %@", call);
|
||||
|
||||
OCTMessageCallEvent event;
|
||||
switch (call.status) {
|
||||
case OCTCallStatusDialing:
|
||||
case OCTCallStatusRinging:
|
||||
event = OCTMessageCallEventUnanswered;
|
||||
break;
|
||||
case OCTCallStatusActive:
|
||||
event = OCTMessageCallEventAnswered;
|
||||
break;
|
||||
}
|
||||
|
||||
OCTMessageCall *messageCall = [OCTMessageCall new];
|
||||
messageCall.callDuration = call.callDuration;
|
||||
messageCall.callEvent = event;
|
||||
|
||||
return [self addMessageAbstractWithChat:call.chat sender:call.caller messageText:nil messageFile:nil messageCall:messageCall tssent:0 tsrcvd:0];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
+ (RLMMigrationBlock)realmMigrationBlock
|
||||
{
|
||||
return ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
|
||||
if (oldSchemaVersion < 1) {
|
||||
// objcTox version 0.1.0
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 2) {
|
||||
// objcTox version 0.2.1
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 3) {
|
||||
// objcTox version 0.4.0
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 4) {
|
||||
// objcTox version 0.5.0
|
||||
[self doMigrationVersion4:migration];
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 5) {
|
||||
// OCTMessageAbstract: chat property replaced with chatUniqueIdentifier
|
||||
[self doMigrationVersion5:migration];
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 6) {
|
||||
// OCTSettingsStorageObject: adding genericSettingsData property.
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 7) {
|
||||
[self doMigrationVersion7:migration];
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 8) {
|
||||
[self doMigrationVersion8:migration];
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 9) {}
|
||||
|
||||
if (oldSchemaVersion < 10) {}
|
||||
|
||||
if (oldSchemaVersion < 11) {
|
||||
[self doMigrationVersion11:migration];
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 12) {
|
||||
[self doMigrationVersion12:migration];
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 13) {
|
||||
[self doMigrationVersion13:migration];
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 14) {
|
||||
[self doMigrationVersion14:migration];
|
||||
}
|
||||
|
||||
if (oldSchemaVersion < 16) {
|
||||
[self doMigrationVersion16:migration];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+ (void)doMigrationVersion4:(RLMMigration *)migration
|
||||
{
|
||||
[migration enumerateObjects:OCTChat.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"enteredText"] = [oldObject[@"enteredText"] length] > 0 ? oldObject[@"enteredText"] : nil;
|
||||
}];
|
||||
|
||||
[migration enumerateObjects:OCTFriend.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"name"] = [oldObject[@"name"] length] > 0 ? oldObject[@"name"] : nil;
|
||||
newObject[@"statusMessage"] = [oldObject[@"statusMessage"] length] > 0 ? oldObject[@"statusMessage"] : nil;
|
||||
}];
|
||||
|
||||
[migration enumerateObjects:OCTFriendRequest.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"message"] = [oldObject[@"message"] length] > 0 ? oldObject[@"message"] : nil;
|
||||
}];
|
||||
|
||||
[migration enumerateObjects:OCTMessageFile.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"fileName"] = [oldObject[@"fileName"] length] > 0 ? oldObject[@"fileName"] : nil;
|
||||
newObject[@"fileUTI"] = [oldObject[@"fileUTI"] length] > 0 ? oldObject[@"fileUTI"] : nil;
|
||||
}];
|
||||
|
||||
[migration enumerateObjects:OCTMessageText.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"text"] = [oldObject[@"text"] length] > 0 ? oldObject[@"text"] : nil;
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)doMigrationVersion5:(RLMMigration *)migration
|
||||
{
|
||||
[migration enumerateObjects:OCTMessageAbstract.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"chatUniqueIdentifier"] = oldObject[@"chat"][@"uniqueIdentifier"];
|
||||
newObject[@"senderUniqueIdentifier"] = oldObject[@"sender"][@"uniqueIdentifier"];
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)doMigrationVersion7:(RLMMigration *)migration
|
||||
{
|
||||
// Before this version OCTMessageText.isDelivered was broken.
|
||||
// See https://github.com/Antidote-for-Tox/objcTox/issues/158
|
||||
//
|
||||
// After update it was fixed + resending of undelivered messages feature was introduced.
|
||||
// This fired resending all messages that were in history for all friends.
|
||||
//
|
||||
// To fix an issue and stop people suffering we mark all outgoing text messages as delivered.
|
||||
|
||||
[migration enumerateObjects:OCTMessageAbstract.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
if (newObject[@"senderUniqueIdentifier"] != nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
RLMObject *messageText = newObject[@"messageText"];
|
||||
|
||||
if (! messageText) {
|
||||
return;
|
||||
}
|
||||
|
||||
messageText[@"isDelivered"] = @YES;
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)doMigrationVersion8:(RLMMigration *)migration
|
||||
{
|
||||
[migration enumerateObjects:OCTFriend.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"pushToken"] = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)doMigrationVersion11:(RLMMigration *)migration
|
||||
{
|
||||
[migration enumerateObjects:OCTFriend.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"msgv3Capability"] = @NO;
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)doMigrationVersion12:(RLMMigration *)migration
|
||||
{
|
||||
[migration enumerateObjects:OCTMessageText.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"msgv3HashHex"] = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)doMigrationVersion13:(RLMMigration *)migration
|
||||
{
|
||||
[migration enumerateObjects:OCTMessageText.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"sentPush"] = @YES;
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)doMigrationVersion14:(RLMMigration *)migration
|
||||
{
|
||||
[migration enumerateObjects:OCTMessageAbstract.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"tssent"] = @0;
|
||||
newObject[@"tsrcvd"] = @0;
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)doMigrationVersion16:(RLMMigration *)migration
|
||||
{
|
||||
[migration enumerateObjects:OCTFriend.className block:^(RLMObject *oldObject, RLMObject *newObject) {
|
||||
newObject[@"capabilities2"] = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* Only one of messageText, messageFile or messageCall can be non-nil.
|
||||
*/
|
||||
- (OCTMessageAbstract *)addMessageAbstractWithChat:(OCTChat *)chat
|
||||
sender:(OCTFriend *)sender
|
||||
messageText:(OCTMessageText *)messageText
|
||||
messageFile:(OCTMessageFile *)messageFile
|
||||
messageCall:(OCTMessageCall *)messageCall
|
||||
tssent:(UInt32)tssent
|
||||
tsrcvd:(UInt32)tsrcvd
|
||||
{
|
||||
NSParameterAssert(chat);
|
||||
|
||||
NSAssert( (messageText && ! messageFile && ! messageCall) ||
|
||||
(! messageText && messageFile && ! messageCall) ||
|
||||
(! messageText && ! messageFile && messageCall),
|
||||
@"Wrong options passed. Only one of messageText, messageFile or messageCall should be non-nil.");
|
||||
|
||||
OCTMessageAbstract *messageAbstract = [OCTMessageAbstract new];
|
||||
messageAbstract.dateInterval = [[NSDate date] timeIntervalSince1970];
|
||||
messageAbstract.senderUniqueIdentifier = sender.uniqueIdentifier;
|
||||
messageAbstract.chatUniqueIdentifier = chat.uniqueIdentifier;
|
||||
messageAbstract.tssent = tssent;
|
||||
messageAbstract.tsrcvd = tsrcvd;
|
||||
messageAbstract.messageText = messageText;
|
||||
messageAbstract.messageFile = messageFile;
|
||||
messageAbstract.messageCall = messageCall;
|
||||
|
||||
[self addObject:messageAbstract];
|
||||
|
||||
[self updateObject:chat withBlock:^(OCTChat *theChat) {
|
||||
theChat.lastMessage = messageAbstract;
|
||||
theChat.lastActivityDateInterval = messageAbstract.dateInterval;
|
||||
}];
|
||||
|
||||
return messageAbstract;
|
||||
}
|
||||
|
||||
// Delete an NSArray, RLMArray, or RLMResults of messages from this Realm.
|
||||
- (void)removeMessagesWithSubmessages:(id)messages
|
||||
{
|
||||
for (OCTMessageAbstract *message in messages) {
|
||||
if (message.messageText) {
|
||||
[self.realm deleteObject:message.messageText];
|
||||
}
|
||||
if (message.messageFile) {
|
||||
[self.realm deleteObject:message.messageFile];
|
||||
}
|
||||
if (message.messageCall) {
|
||||
[self.realm deleteObject:message.messageCall];
|
||||
}
|
||||
}
|
||||
|
||||
[self.realm deleteObjects:messages];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,31 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTToxConstants.h"
|
||||
|
||||
@class OCTMessageAbstract;
|
||||
|
||||
@interface NSError (OCTFile)
|
||||
|
||||
+ (NSError *)sendFileErrorInternalError;
|
||||
+ (NSError *)sendFileErrorCannotReadFile;
|
||||
+ (NSError *)sendFileErrorCannotSaveFileToUploads;
|
||||
+ (NSError *)sendFileErrorFriendNotFound;
|
||||
+ (NSError *)sendFileErrorFriendNotConnected;
|
||||
+ (NSError *)sendFileErrorNameTooLong;
|
||||
+ (NSError *)sendFileErrorTooMany;
|
||||
+ (NSError *)sendFileErrorFromToxFileSendError:(OCTToxErrorFileSend)code;
|
||||
|
||||
+ (NSError *)acceptFileErrorInternalError;
|
||||
+ (NSError *)acceptFileErrorCannotWriteToFile;
|
||||
+ (NSError *)acceptFileErrorFriendNotFound;
|
||||
+ (NSError *)acceptFileErrorFriendNotConnected;
|
||||
+ (NSError *)acceptFileErrorWrongMessage:(OCTMessageAbstract *)message;
|
||||
+ (NSError *)acceptFileErrorFromToxFileSendChunkError:(OCTToxErrorFileSendChunk)code;
|
||||
+ (NSError *)acceptFileErrorFromToxFileControl:(OCTToxErrorFileControl)code;
|
||||
|
||||
+ (NSError *)fileTransferErrorWrongMessage:(OCTMessageAbstract *)message;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,189 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "NSError+OCTFile.h"
|
||||
#import "OCTManagerConstants.h"
|
||||
|
||||
@implementation NSError (OCTFile)
|
||||
|
||||
+ (NSError *)sendFileErrorInternalError
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTSendFileErrorInternalError
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Send file",
|
||||
NSLocalizedFailureReasonErrorKey : @"Internal error",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)sendFileErrorCannotReadFile
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTSendFileErrorCannotReadFile
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Send file",
|
||||
NSLocalizedFailureReasonErrorKey : @"Cannot read file",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)sendFileErrorCannotSaveFileToUploads
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTSendFileErrorCannotSaveFileToUploads
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Send file",
|
||||
NSLocalizedFailureReasonErrorKey : @"Cannot save send file to uploads folder.",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)sendFileErrorFriendNotFound
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTSendFileErrorFriendNotFound
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Send file",
|
||||
NSLocalizedFailureReasonErrorKey : @"Friend to send file to was not found.",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)sendFileErrorFriendNotConnected
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTSendFileErrorFriendNotConnected
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Send file",
|
||||
NSLocalizedFailureReasonErrorKey : @"Friend is not connected at the moment.",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)sendFileErrorNameTooLong
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTSendFileErrorFriendNotConnected
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Send file",
|
||||
NSLocalizedFailureReasonErrorKey : @"File name is too long.",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)sendFileErrorTooMany
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTSendFileErrorFriendNotConnected
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Send file",
|
||||
NSLocalizedFailureReasonErrorKey : @"Too many active file transfers.",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)sendFileErrorFromToxFileSendError:(OCTToxErrorFileSend)code
|
||||
{
|
||||
switch (code) {
|
||||
case OCTToxErrorFileSendUnknown:
|
||||
return [self sendFileErrorInternalError];
|
||||
case OCTToxErrorFileSendFriendNotFound:
|
||||
return [self sendFileErrorFriendNotFound];
|
||||
case OCTToxErrorFileSendFriendNotConnected:
|
||||
return [self sendFileErrorFriendNotConnected];
|
||||
case OCTToxErrorFileSendNameTooLong:
|
||||
return [self sendFileErrorNameTooLong];
|
||||
case OCTToxErrorFileSendTooMany:
|
||||
return [self sendFileErrorTooMany];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSError *)acceptFileErrorInternalError
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTAcceptFileErrorInternalError
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Download file",
|
||||
NSLocalizedFailureReasonErrorKey : @"Internal error",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)acceptFileErrorCannotWriteToFile
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTAcceptFileErrorCannotWriteToFile
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Download file",
|
||||
NSLocalizedFailureReasonErrorKey : @"File is not available for writing.",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)acceptFileErrorFriendNotFound
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTAcceptFileErrorFriendNotFound
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Download file",
|
||||
NSLocalizedFailureReasonErrorKey : @"Friend to send file to was not found.",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)acceptFileErrorFriendNotConnected
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTAcceptFileErrorFriendNotConnected
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Download file",
|
||||
NSLocalizedFailureReasonErrorKey : @"Friend is not connected at the moment.",
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)acceptFileErrorWrongMessage:(OCTMessageAbstract *)message
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTAcceptFileErrorWrongMessage
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Download file",
|
||||
NSLocalizedFailureReasonErrorKey : [NSString stringWithFormat:@"Specified wrong message %@", message],
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSError *)acceptFileErrorFromToxFileSendChunkError:(OCTToxErrorFileSendChunk)code
|
||||
{
|
||||
switch (code) {
|
||||
case OCTToxErrorFileSendChunkFriendNotFound:
|
||||
return [self acceptFileErrorFriendNotFound];
|
||||
case OCTToxErrorFileSendChunkFriendNotConnected:
|
||||
return [self acceptFileErrorFriendNotConnected];
|
||||
case OCTToxErrorFileSendChunkUnknown:
|
||||
case OCTToxErrorFileSendChunkNotFound:
|
||||
case OCTToxErrorFileSendChunkNotTransferring:
|
||||
case OCTToxErrorFileSendChunkInvalidLength:
|
||||
case OCTToxErrorFileSendChunkSendq:
|
||||
case OCTToxErrorFileSendChunkWrongPosition:
|
||||
return [self acceptFileErrorInternalError];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSError *)acceptFileErrorFromToxFileControl:(OCTToxErrorFileControl)code
|
||||
{
|
||||
switch (code) {
|
||||
case OCTToxErrorFileControlFriendNotFound:
|
||||
return [self acceptFileErrorFriendNotFound];
|
||||
case OCTToxErrorFileControlFriendNotConnected:
|
||||
return [self acceptFileErrorFriendNotConnected];
|
||||
case OCTToxErrorFileControlNotFound:
|
||||
case OCTToxErrorFileControlNotPaused:
|
||||
case OCTToxErrorFileControlDenied:
|
||||
case OCTToxErrorFileControlAlreadyPaused:
|
||||
case OCTToxErrorFileControlSendq:
|
||||
return [self acceptFileErrorInternalError];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSError *)fileTransferErrorWrongMessage:(OCTMessageAbstract *)message
|
||||
{
|
||||
return [NSError errorWithDomain:kOCTManagerErrorDomain
|
||||
code:OCTFileTransferErrorWrongMessage
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Error",
|
||||
NSLocalizedFailureReasonErrorKey : [NSString stringWithFormat:@"Specified wrong message %@", message],
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,42 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFileBaseOperation.h"
|
||||
|
||||
@interface OCTFileBaseOperation (Private)
|
||||
|
||||
@property (weak, nonatomic, readonly, nullable) OCTTox *tox;
|
||||
|
||||
@property (assign, nonatomic, readonly) OCTToxFriendNumber friendNumber;
|
||||
@property (assign, nonatomic, readonly) OCTToxFileNumber fileNumber;
|
||||
@property (assign, nonatomic, readonly) OCTToxFileSize fileSize;
|
||||
|
||||
/**
|
||||
* Override this method to start custom actions. Call finish when operation is done.
|
||||
*/
|
||||
- (void)operationStarted NS_REQUIRES_SUPER;
|
||||
|
||||
/**
|
||||
* Override this method to do clean up on operation cancellation.
|
||||
*/
|
||||
- (void)operationWasCanceled NS_REQUIRES_SUPER;
|
||||
|
||||
/**
|
||||
* Call this method to change bytes done value.
|
||||
*/
|
||||
- (void)updateBytesDone:(OCTToxFileSize)bytesDone;
|
||||
|
||||
/**
|
||||
* Call this method in case if operation was finished.
|
||||
*/
|
||||
- (void)finishWithSuccess;
|
||||
|
||||
/**
|
||||
* Call this method in case if operation was finished or cancelled with error.
|
||||
*
|
||||
* @param error Pass error if occured, nil on success.
|
||||
*/
|
||||
- (void)finishWithError:(nonnull NSError *)error;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,85 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTTox.h"
|
||||
#import "OCTToxConstants.h"
|
||||
|
||||
@class OCTFileBaseOperation;
|
||||
|
||||
/**
|
||||
* Block to notify about operation progress.
|
||||
*
|
||||
* @param operation Operation that is running.
|
||||
* @param progress Progress of operation. From 0.0 to 1.0.
|
||||
* @param bytesPerSecond Speed of loading.
|
||||
* @param eta Estimated time of finish of loading.
|
||||
*/
|
||||
typedef void (^OCTFileBaseOperationProgressBlock)(OCTFileBaseOperation *__nonnull operation);
|
||||
|
||||
/**
|
||||
* Block to notify about operation success.
|
||||
*
|
||||
* @param operation Operation that is running.
|
||||
* @param filePath Path of file being loaded
|
||||
*/
|
||||
typedef void (^OCTFileBaseOperationSuccessBlock)(OCTFileBaseOperation *__nonnull operation);
|
||||
|
||||
/**
|
||||
* Block to notify about operation failure.
|
||||
*
|
||||
* @param operation Operation that is running.
|
||||
*/
|
||||
typedef void (^OCTFileBaseOperationFailureBlock)(OCTFileBaseOperation *__nonnull operation, NSError *__nonnull error);
|
||||
|
||||
|
||||
@interface OCTFileBaseOperation : NSOperation
|
||||
|
||||
/**
|
||||
* Identifier of operation, unique for all active file operations.
|
||||
*/
|
||||
@property (strong, nonatomic, readonly, nonnull) NSString *operationId;
|
||||
|
||||
/**
|
||||
* Progress properties.
|
||||
*/
|
||||
@property (assign, nonatomic, readonly) OCTToxFileSize bytesDone;
|
||||
@property (assign, nonatomic, readonly) float progress;
|
||||
@property (assign, nonatomic, readonly) OCTToxFileSize bytesPerSecond;
|
||||
@property (assign, nonatomic, readonly) CFTimeInterval eta;
|
||||
|
||||
@property (strong, nonatomic, readonly, nullable) NSDictionary *userInfo;
|
||||
|
||||
/**
|
||||
* Creates operation id from file and friend number.
|
||||
*/
|
||||
+ (nonnull NSString *)operationIdFromFileNumber:(OCTToxFileNumber)fileNumber friendNumber:(OCTToxFriendNumber)friendNumber;
|
||||
|
||||
/**
|
||||
* Create operation.
|
||||
*
|
||||
* @param tox Tox object to load from.
|
||||
* @param friendNumber Number of friend.
|
||||
* @param fileNumber Number of file to load.
|
||||
* @param fileSize Size of file in bytes.
|
||||
* @param userInfo Any object that will be stored by operation.
|
||||
* @param progressBlock Block called to notify about loading progress. Block will be called on main thread.
|
||||
* @param etaUpdateBlock Block called to notify about loading eta update. Block will be called on main thread.
|
||||
* @param successBlock Block called on operation success. Block will be called on main thread.
|
||||
* @param failureBlock Block called on loading error. Block will be called on main thread.
|
||||
*/
|
||||
- (nullable instancetype)initWithTox:(nonnull OCTTox *)tox
|
||||
friendNumber:(OCTToxFriendNumber)friendNumber
|
||||
fileNumber:(OCTToxFileNumber)fileNumber
|
||||
fileSize:(OCTToxFileSize)fileSize
|
||||
userInfo:(nullable NSDictionary *)userInfo
|
||||
progressBlock:(nullable OCTFileBaseOperationProgressBlock)progressBlock
|
||||
etaUpdateBlock:(nullable OCTFileBaseOperationProgressBlock)etaUpdateBlock
|
||||
successBlock:(nullable OCTFileBaseOperationSuccessBlock)successBlock
|
||||
failureBlock:(nullable OCTFileBaseOperationFailureBlock)failureBlock;
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
+ (nullable instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,286 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFileBaseOperation.h"
|
||||
#import "OCTFileBaseOperation+Private.h"
|
||||
#import "OCTLogging.h"
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
static const CFTimeInterval kMinUpdateProgressInterval = 0.1;
|
||||
static const CFTimeInterval kMinUpdateEtaInterval = 1.0;
|
||||
|
||||
@interface OCTEtaObject : NSObject
|
||||
@property (assign, nonatomic) CFTimeInterval deltaTime;
|
||||
@property (assign, nonatomic) OCTToxFileSize deltaBytes;
|
||||
@end
|
||||
|
||||
@implementation OCTEtaObject
|
||||
@end
|
||||
|
||||
@interface OCTFileBaseOperation ()
|
||||
|
||||
@property (assign, atomic) BOOL privateExecuting;
|
||||
@property (assign, atomic) BOOL privateFinished;
|
||||
|
||||
@property (weak, nonatomic, readonly, nullable) OCTTox *tox;
|
||||
|
||||
@property (assign, nonatomic, readonly) OCTToxFriendNumber friendNumber;
|
||||
@property (assign, nonatomic, readonly) OCTToxFileNumber fileNumber;
|
||||
@property (assign, nonatomic, readonly) OCTToxFileSize fileSize;
|
||||
|
||||
@property (assign, nonatomic, readwrite) OCTToxFileSize bytesDone;
|
||||
@property (assign, nonatomic, readwrite) float progress;
|
||||
@property (assign, nonatomic, readwrite) OCTToxFileSize bytesPerSecond;
|
||||
@property (assign, nonatomic, readwrite) CFTimeInterval eta;
|
||||
|
||||
@property (copy, nonatomic) OCTFileBaseOperationProgressBlock progressBlock;
|
||||
@property (copy, nonatomic) OCTFileBaseOperationProgressBlock etaUpdateBlock;
|
||||
@property (copy, nonatomic) OCTFileBaseOperationSuccessBlock successBlock;
|
||||
@property (copy, nonatomic) OCTFileBaseOperationFailureBlock failureBlock;
|
||||
|
||||
@property (assign, nonatomic) CFTimeInterval lastUpdateProgressTime;
|
||||
@property (assign, nonatomic) OCTToxFileSize lastUpdateBytesDone;
|
||||
@property (assign, nonatomic) CFTimeInterval lastUpdateEtaProgressTime;
|
||||
@property (assign, nonatomic) OCTToxFileSize lastUpdateEtaBytesDone;
|
||||
|
||||
@property (strong, nonatomic) NSMutableArray *last10EtaObjects;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTFileBaseOperation
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (NSString *)operationIdFromFileNumber:(OCTToxFileNumber)fileNumber friendNumber:(OCTToxFriendNumber)friendNumber
|
||||
{
|
||||
return [NSString stringWithFormat:@"%d-%d", fileNumber, friendNumber];
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (nullable instancetype)initWithTox:(nonnull OCTTox *)tox
|
||||
friendNumber:(OCTToxFriendNumber)friendNumber
|
||||
fileNumber:(OCTToxFileNumber)fileNumber
|
||||
fileSize:(OCTToxFileSize)fileSize
|
||||
userInfo:(NSDictionary *)userInfo
|
||||
progressBlock:(nullable OCTFileBaseOperationProgressBlock)progressBlock
|
||||
etaUpdateBlock:(nullable OCTFileBaseOperationProgressBlock)etaUpdateBlock
|
||||
successBlock:(nullable OCTFileBaseOperationSuccessBlock)successBlock
|
||||
failureBlock:(nullable OCTFileBaseOperationFailureBlock)failureBlock
|
||||
{
|
||||
NSParameterAssert(tox);
|
||||
NSParameterAssert(fileSize > 0);
|
||||
|
||||
self = [super init];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_operationId = [[self class] operationIdFromFileNumber:fileNumber friendNumber:friendNumber];
|
||||
|
||||
_tox = tox;
|
||||
|
||||
_friendNumber = friendNumber;
|
||||
_fileNumber = fileNumber;
|
||||
_fileSize = fileSize;
|
||||
|
||||
_progress = 0.0;
|
||||
_bytesPerSecond = 0;
|
||||
_eta = 0;
|
||||
|
||||
_userInfo = userInfo;
|
||||
|
||||
_progressBlock = [progressBlock copy];
|
||||
_etaUpdateBlock = [etaUpdateBlock copy];
|
||||
_successBlock = [successBlock copy];
|
||||
_failureBlock = [failureBlock copy];
|
||||
|
||||
_bytesDone = 0;
|
||||
_lastUpdateProgressTime = 0;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (void)setExecuting:(BOOL)executing
|
||||
{
|
||||
[self willChangeValueForKey:@"isExecuting"];
|
||||
self.privateExecuting = executing;
|
||||
[self didChangeValueForKey:@"isExecuting"];
|
||||
}
|
||||
|
||||
- (BOOL)isExecuting
|
||||
{
|
||||
return self.privateExecuting;
|
||||
}
|
||||
|
||||
- (void)setFinished:(BOOL)finished
|
||||
{
|
||||
[self willChangeValueForKey:@"isFinished"];
|
||||
self.privateFinished = finished;
|
||||
[self didChangeValueForKey:@"isFinished"];
|
||||
}
|
||||
|
||||
- (BOOL)isFinished
|
||||
{
|
||||
return self.privateFinished;
|
||||
}
|
||||
|
||||
#pragma mark - Private category
|
||||
|
||||
- (void)updateBytesDone:(OCTToxFileSize)bytesDone
|
||||
{
|
||||
self.bytesDone = bytesDone;
|
||||
|
||||
[self updateProgressIfNeeded:bytesDone];
|
||||
[self updateEtaIfNeeded:bytesDone];
|
||||
}
|
||||
|
||||
- (void)operationStarted
|
||||
{
|
||||
OCTLogInfo(@"start loading file with identifier %@", self.operationId);
|
||||
}
|
||||
|
||||
- (void)operationWasCanceled
|
||||
{
|
||||
OCTLogInfo(@"was cancelled");
|
||||
}
|
||||
|
||||
- (void)finishWithSuccess
|
||||
{
|
||||
OCTLogInfo(@"finished with success");
|
||||
|
||||
self.executing = NO;
|
||||
self.finished = YES;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.successBlock) {
|
||||
self.successBlock(self);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)finishWithError:(nonnull NSError *)error
|
||||
{
|
||||
NSParameterAssert(error);
|
||||
|
||||
OCTLogInfo(@"finished with error %@", error);
|
||||
|
||||
self.executing = NO;
|
||||
self.finished = YES;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.failureBlock) {
|
||||
self.failureBlock(self, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Override
|
||||
|
||||
- (void)start
|
||||
{
|
||||
if (self.cancelled) {
|
||||
self.finished = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
self.executing = YES;
|
||||
|
||||
self.lastUpdateProgressTime = CACurrentMediaTime();
|
||||
self.lastUpdateBytesDone = 0;
|
||||
self.lastUpdateEtaProgressTime = CACurrentMediaTime();
|
||||
self.lastUpdateEtaBytesDone = 0;
|
||||
self.last10EtaObjects = [NSMutableArray new];
|
||||
|
||||
[self operationStarted];
|
||||
}
|
||||
|
||||
- (void)cancel
|
||||
{
|
||||
[super cancel];
|
||||
|
||||
[self operationWasCanceled];
|
||||
|
||||
self.executing = NO;
|
||||
self.finished = YES;
|
||||
}
|
||||
|
||||
- (BOOL)asynchronous
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)updateProgressIfNeeded:(OCTToxFileSize)bytesDone
|
||||
{
|
||||
CFTimeInterval time = CACurrentMediaTime();
|
||||
|
||||
CFTimeInterval deltaTime = time - self.lastUpdateProgressTime;
|
||||
|
||||
if (deltaTime <= kMinUpdateProgressInterval) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.lastUpdateProgressTime = time;
|
||||
self.lastUpdateBytesDone = bytesDone;
|
||||
|
||||
self.progress = (float)bytesDone / self.fileSize;
|
||||
|
||||
OCTLogInfo(@"progress %.2f, bytes per second %lld, eta %.0f seconds", self.progress, self.bytesPerSecond, self.eta);
|
||||
|
||||
if (self.progressBlock) {
|
||||
self.progressBlock(self);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateEtaIfNeeded:(OCTToxFileSize)bytesDone
|
||||
{
|
||||
CFTimeInterval time = CACurrentMediaTime();
|
||||
|
||||
CFTimeInterval deltaTime = time - self.lastUpdateEtaProgressTime;
|
||||
|
||||
if (deltaTime <= kMinUpdateEtaInterval) {
|
||||
return;
|
||||
}
|
||||
|
||||
OCTToxFileSize deltaBytes = bytesDone - self.lastUpdateEtaBytesDone;
|
||||
OCTToxFileSize bytesLeft = self.fileSize - bytesDone;
|
||||
|
||||
self.lastUpdateEtaProgressTime = time;
|
||||
self.lastUpdateEtaBytesDone = bytesDone;
|
||||
|
||||
OCTEtaObject *etaObject = [OCTEtaObject new];
|
||||
etaObject.deltaTime = deltaTime;
|
||||
etaObject.deltaBytes = deltaBytes;
|
||||
|
||||
[self.last10EtaObjects addObject:etaObject];
|
||||
if (self.last10EtaObjects.count > 10) {
|
||||
[self.last10EtaObjects removeObjectAtIndex:0];
|
||||
}
|
||||
|
||||
CFTimeInterval totalDeltaTime = 0.0;
|
||||
OCTToxFileSize totalDeltaBytes = 0;
|
||||
|
||||
for (OCTEtaObject *object in self.last10EtaObjects) {
|
||||
totalDeltaTime += object.deltaTime;
|
||||
totalDeltaBytes += object.deltaBytes;
|
||||
}
|
||||
|
||||
self.bytesPerSecond = totalDeltaBytes / totalDeltaTime;
|
||||
|
||||
if (totalDeltaBytes) {
|
||||
self.eta = totalDeltaTime * bytesLeft / totalDeltaBytes;
|
||||
}
|
||||
|
||||
if (self.etaUpdateBlock) {
|
||||
self.etaUpdateBlock(self);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,15 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTFileInputProtocol.h"
|
||||
|
||||
@interface OCTFileDataInput : NSObject <OCTFileInputProtocol>
|
||||
|
||||
- (nullable instancetype)initWithData:(nonnull NSData *)data;
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
+ (nullable instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,50 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFileDataInput.h"
|
||||
#import "OCTLogging.h"
|
||||
|
||||
@interface OCTFileDataInput ()
|
||||
|
||||
@property (strong, nonatomic, readonly) NSData *data;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTFileDataInput
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (nullable instancetype)initWithData:(nonnull NSData *)data
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_data = data;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - OCTFileInputProtocol
|
||||
|
||||
- (BOOL)prepareToRead
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (nonnull NSData *)bytesWithPosition:(OCTToxFileSize)position length:(size_t)length
|
||||
{
|
||||
@try {
|
||||
return [self.data subdataWithRange:NSMakeRange((NSUInteger)position, length)];
|
||||
}
|
||||
@catch (NSException *ex) {
|
||||
OCTLogWarn(@"catched exception %@", ex);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,15 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTFileOutputProtocol.h"
|
||||
|
||||
@interface OCTFileDataOutput : NSObject <OCTFileOutputProtocol>
|
||||
|
||||
/**
|
||||
* Result data. This property will contain data only after download finishes.
|
||||
*/
|
||||
@property (strong, nonatomic, readonly, nullable) NSData *resultData;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,42 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFileDataOutput.h"
|
||||
|
||||
@interface OCTFileDataOutput ()
|
||||
|
||||
@property (strong, nonatomic) NSMutableData *tempData;
|
||||
@property (strong, nonatomic) NSData *resultData;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTFileDataOutput
|
||||
|
||||
#pragma mark - OCTFileOutputProtocol
|
||||
|
||||
- (BOOL)prepareToWrite
|
||||
{
|
||||
self.tempData = [NSMutableData new];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)writeData:(nonnull NSData *)data
|
||||
{
|
||||
[self.tempData appendData:data];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)finishWriting
|
||||
{
|
||||
self.resultData = [self.tempData copy];
|
||||
self.tempData = nil;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)cancel
|
||||
{
|
||||
self.tempData = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,45 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFileBaseOperation.h"
|
||||
|
||||
@class OCTTox;
|
||||
@protocol OCTFileOutputProtocol;
|
||||
|
||||
/**
|
||||
* File operation for downloading file.
|
||||
*
|
||||
* When started will automatically send resume control to friend.
|
||||
*/
|
||||
@interface OCTFileDownloadOperation : OCTFileBaseOperation
|
||||
|
||||
@property (strong, nonatomic, readonly, nonnull) id<OCTFileOutputProtocol> output;
|
||||
|
||||
/**
|
||||
* Create operation.
|
||||
*
|
||||
* @param fileOutput Output to use as a destination for file transfer.
|
||||
*
|
||||
* For other parameters description see OCTFileBaseOperation.
|
||||
*/
|
||||
- (nullable instancetype)initWithTox:(nonnull OCTTox *)tox
|
||||
fileOutput:(nonnull id<OCTFileOutputProtocol>)fileOutput
|
||||
friendNumber:(OCTToxFriendNumber)friendNumber
|
||||
fileNumber:(OCTToxFileNumber)fileNumber
|
||||
fileSize:(OCTToxFileSize)fileSize
|
||||
userInfo:(nullable NSDictionary *)userInfo
|
||||
progressBlock:(nullable OCTFileBaseOperationProgressBlock)progressBlock
|
||||
etaUpdateBlock:(nullable OCTFileBaseOperationProgressBlock)etaUpdateBlock
|
||||
successBlock:(nullable OCTFileBaseOperationSuccessBlock)successBlock
|
||||
failureBlock:(nullable OCTFileBaseOperationFailureBlock)failureBlock;
|
||||
|
||||
/**
|
||||
* Call this method to get next chunk to operation.
|
||||
*
|
||||
* @param chunk Next chunk of data to append to file.
|
||||
* @param position Position in file to append chunk.
|
||||
*/
|
||||
- (void)receiveChunk:(nullable NSData *)chunk position:(OCTToxFileSize)position;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,111 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFileDownloadOperation.h"
|
||||
#import "OCTFileBaseOperation+Private.h"
|
||||
#import "OCTFileOutputProtocol.h"
|
||||
#import "OCTLogging.h"
|
||||
#import "NSError+OCTFile.h"
|
||||
|
||||
@interface OCTFileDownloadOperation ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTFileDownloadOperation
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (nullable instancetype)initWithTox:(nonnull OCTTox *)tox
|
||||
fileOutput:(nonnull id<OCTFileOutputProtocol>)fileOutput
|
||||
friendNumber:(OCTToxFriendNumber)friendNumber
|
||||
fileNumber:(OCTToxFileNumber)fileNumber
|
||||
fileSize:(OCTToxFileSize)fileSize
|
||||
userInfo:(NSDictionary *)userInfo
|
||||
progressBlock:(nullable OCTFileBaseOperationProgressBlock)progressBlock
|
||||
etaUpdateBlock:(nullable OCTFileBaseOperationProgressBlock)etaUpdateBlock
|
||||
successBlock:(nullable OCTFileBaseOperationSuccessBlock)successBlock
|
||||
failureBlock:(nullable OCTFileBaseOperationFailureBlock)failureBlock
|
||||
{
|
||||
NSParameterAssert(fileOutput);
|
||||
|
||||
self = [super initWithTox:tox
|
||||
friendNumber:friendNumber
|
||||
fileNumber:fileNumber
|
||||
fileSize:fileSize
|
||||
userInfo:userInfo
|
||||
progressBlock:progressBlock
|
||||
etaUpdateBlock:etaUpdateBlock
|
||||
successBlock:successBlock
|
||||
failureBlock:failureBlock];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_output = fileOutput;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)receiveChunk:(NSData *)chunk position:(OCTToxFileSize)position
|
||||
{
|
||||
if (! chunk) {
|
||||
if ([self.output finishWriting]) {
|
||||
[self finishWithSuccess];
|
||||
}
|
||||
else {
|
||||
[self finishWithError:[NSError acceptFileErrorCannotWriteToFile]];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.bytesDone != position) {
|
||||
OCTLogWarn(@"bytesDone doesn't match position");
|
||||
[self.tox fileSendControlForFileNumber:self.fileNumber
|
||||
friendNumber:self.friendNumber
|
||||
control:OCTToxFileControlCancel
|
||||
error:nil];
|
||||
[self finishWithError:[NSError acceptFileErrorInternalError]];
|
||||
return;
|
||||
}
|
||||
|
||||
if (! [self.output writeData:chunk]) {
|
||||
[self finishWithError:[NSError acceptFileErrorCannotWriteToFile]];
|
||||
return;
|
||||
}
|
||||
|
||||
[self updateBytesDone:self.bytesDone + chunk.length];
|
||||
}
|
||||
|
||||
#pragma mark - Override
|
||||
|
||||
- (void)operationStarted
|
||||
{
|
||||
[super operationStarted];
|
||||
|
||||
if (! [self.output prepareToWrite]) {
|
||||
[self finishWithError:[NSError acceptFileErrorCannotWriteToFile]];
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
if (! [self.tox fileSendControlForFileNumber:self.fileNumber
|
||||
friendNumber:self.friendNumber
|
||||
control:OCTToxFileControlResume
|
||||
error:&error]) {
|
||||
OCTLogWarn(@"cannot send control %@", error);
|
||||
[self finishWithError:[NSError acceptFileErrorFromToxFileControl:error.code]];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)operationWasCanceled
|
||||
{
|
||||
[super operationWasCanceled];
|
||||
|
||||
[self.output cancel];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,27 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTToxConstants.h"
|
||||
|
||||
@protocol OCTFileInputProtocol <NSObject>
|
||||
|
||||
/**
|
||||
* Prepare input to read. This method will be called before first call to bytesWithPosition:length:.
|
||||
*
|
||||
* @return YES on success, NO on failure.
|
||||
*/
|
||||
- (BOOL)prepareToRead;
|
||||
|
||||
/**
|
||||
* Provide bytes.
|
||||
*
|
||||
* @param position Start position to start reading from.
|
||||
* @param length Length of bytes to read.
|
||||
*
|
||||
* @return NSData on success, nil on failure
|
||||
*/
|
||||
- (nonnull NSData *)bytesWithPosition:(OCTToxFileSize)position length:(size_t)length;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,37 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol OCTFileOutputProtocol <NSObject>
|
||||
|
||||
/**
|
||||
* Prepare input to write. This method will be called before first call to writeData:.
|
||||
*
|
||||
* @return YES on success, NO on failure.
|
||||
*/
|
||||
- (BOOL)prepareToWrite;
|
||||
|
||||
/**
|
||||
* Write data to output.
|
||||
*
|
||||
* @param data Data to write.
|
||||
*
|
||||
* @return YES on success, NO on failure.
|
||||
*/
|
||||
- (BOOL)writeData:(nonnull NSData *)data;
|
||||
|
||||
/**
|
||||
* This method is called after last writeData: method.
|
||||
*
|
||||
* @return YES on success, NO on failure.
|
||||
*/
|
||||
- (BOOL)finishWriting;
|
||||
|
||||
/**
|
||||
* This method is called if all progress was canceled. Do needed cleanup.
|
||||
*/
|
||||
- (void)cancel;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,15 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTFileInputProtocol.h"
|
||||
|
||||
@interface OCTFilePathInput : NSObject <OCTFileInputProtocol>
|
||||
|
||||
- (nullable instancetype)initWithFilePath:(nonnull NSString *)filePath;
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
+ (nullable instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,61 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFilePathInput.h"
|
||||
#import "OCTLogging.h"
|
||||
|
||||
@interface OCTFilePathInput ()
|
||||
|
||||
@property (strong, nonatomic, readonly) NSString *filePath;
|
||||
@property (strong, nonatomic) NSFileHandle *handle;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTFilePathInput
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (nullable instancetype)initWithFilePath:(nonnull NSString *)filePath
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_filePath = filePath;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - OCTFileInputProtocol
|
||||
|
||||
- (BOOL)prepareToRead
|
||||
{
|
||||
self.handle = [NSFileHandle fileHandleForReadingAtPath:self.filePath];
|
||||
|
||||
if (! self.handle) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSData *)bytesWithPosition:(OCTToxFileSize)position length:(size_t)length
|
||||
{
|
||||
@try {
|
||||
if (self.handle.offsetInFile != position) {
|
||||
[self.handle seekToFileOffset:position];
|
||||
}
|
||||
|
||||
return [self.handle readDataOfLength:length];
|
||||
}
|
||||
@catch (NSException *ex) {
|
||||
OCTLogWarn(@"catched exception %@", ex);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,19 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTFileOutputProtocol.h"
|
||||
|
||||
@interface OCTFilePathOutput : NSObject <OCTFileOutputProtocol>
|
||||
|
||||
@property (copy, nonatomic, readonly, nonnull) NSString *resultFilePath;
|
||||
|
||||
- (nullable instancetype)initWithTempFolder:(nonnull NSString *)tempFolder
|
||||
resultFolder:(nonnull NSString *)resultFolder
|
||||
fileName:(nonnull NSString *)fileName;
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
+ (nullable instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,100 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFilePathOutput.h"
|
||||
#import "OCTLogging.h"
|
||||
#import "OCTFileTools.h"
|
||||
|
||||
@interface OCTFilePathOutput ()
|
||||
|
||||
@property (copy, nonatomic, readonly, nonnull) NSString *tempFilePath;
|
||||
|
||||
@property (strong, nonatomic) NSFileHandle *handle;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTFilePathOutput
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (nullable instancetype)initWithTempFolder:(nonnull NSString *)tempFolder
|
||||
resultFolder:(nonnull NSString *)resultFolder
|
||||
fileName:(nonnull NSString *)fileName
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_tempFilePath = [OCTFileTools createNewFilePathInDirectory:tempFolder fileName:fileName];
|
||||
_resultFilePath = [OCTFileTools createNewFilePathInDirectory:resultFolder fileName:fileName];
|
||||
|
||||
// Create dummy file to reserve fileName.
|
||||
[[NSFileManager defaultManager] createFileAtPath:_resultFilePath contents:[NSData data] attributes:nil];
|
||||
|
||||
OCTLogInfo(@"temp path %@", _tempFilePath);
|
||||
OCTLogInfo(@"result path %@", _resultFilePath);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - OCTFileOutputProtocol
|
||||
|
||||
- (BOOL)prepareToWrite
|
||||
{
|
||||
if (! [[NSFileManager defaultManager] createFileAtPath:self.tempFilePath contents:nil attributes:nil]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
self.handle = [NSFileHandle fileHandleForWritingAtPath:self.tempFilePath];
|
||||
|
||||
if (! self.handle) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)writeData:(nonnull NSData *)data
|
||||
{
|
||||
@try {
|
||||
[self.handle writeData:data];
|
||||
return YES;
|
||||
}
|
||||
@catch (NSException *ex) {
|
||||
OCTLogWarn(@"catched exception %@", ex);
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)finishWriting
|
||||
{
|
||||
@try {
|
||||
[self.handle synchronizeFile];
|
||||
}
|
||||
@catch (NSException *ex) {
|
||||
OCTLogWarn(@"catched exception %@", ex);
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
// Remove dummy file.
|
||||
if (! [fileManager removeItemAtPath:self.resultFilePath error:nil]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [[NSFileManager defaultManager] moveItemAtPath:self.tempFilePath toPath:self.resultFilePath error:nil];
|
||||
}
|
||||
|
||||
- (void)cancel
|
||||
{
|
||||
self.handle = nil;
|
||||
|
||||
[[NSFileManager defaultManager] removeItemAtPath:self.tempFilePath error:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,20 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface OCTFileTools : NSObject
|
||||
|
||||
/**
|
||||
* Creates filePath in directory for given fileName. In case if file already exists appends " N" suffix,
|
||||
* e.g. "file 2.txt", "file 3.txt".
|
||||
*
|
||||
* @param directory Directory part of filePath.
|
||||
* @param fileName Name of the file to use in path.
|
||||
*
|
||||
* @return File path to file that does not exist.
|
||||
*/
|
||||
+ (nonnull NSString *)createNewFilePathInDirectory:(nonnull NSString *)directory fileName:(nonnull NSString *)fileName;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,77 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFileTools.h"
|
||||
|
||||
@implementation OCTFileTools
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
+ (nonnull NSString *)createNewFilePathInDirectory:(nonnull NSString *)directory fileName:(nonnull NSString *)fileName
|
||||
{
|
||||
NSParameterAssert(directory);
|
||||
NSParameterAssert(fileName);
|
||||
|
||||
NSString *path = [directory stringByAppendingPathComponent:fileName];
|
||||
|
||||
if (! [self fileExistsAtPath:path]) {
|
||||
return path;
|
||||
}
|
||||
|
||||
NSString *base;
|
||||
NSString *pathExtension = [fileName pathExtension];
|
||||
NSInteger suffix;
|
||||
|
||||
[self getBaseString:&base andSuffix:&suffix fromString:[fileName stringByDeletingPathExtension]];
|
||||
|
||||
while (YES) {
|
||||
NSString *resultName = [base stringByAppendingFormat:@" %ld", (long)suffix];
|
||||
|
||||
if (pathExtension.length > 0) {
|
||||
resultName = [resultName stringByAppendingPathExtension:pathExtension];
|
||||
}
|
||||
|
||||
NSString *path = [directory stringByAppendingPathComponent:resultName];
|
||||
|
||||
if (! [self fileExistsAtPath:path]) {
|
||||
return path;
|
||||
}
|
||||
|
||||
suffix++;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
+ (BOOL)fileExistsAtPath:(NSString *)filePath
|
||||
{
|
||||
return [[NSFileManager defaultManager] fileExistsAtPath:filePath];
|
||||
}
|
||||
|
||||
+ (void)getBaseString:(NSString **)baseString andSuffix:(NSInteger *)suffix fromString:(NSString *)original
|
||||
{
|
||||
NSString *tempBase = original;
|
||||
NSInteger tempSuffix = 1;
|
||||
|
||||
NSArray *components = [tempBase componentsSeparatedByString:@" "];
|
||||
|
||||
if (components.count > 1) {
|
||||
NSString *lastComponent = components.lastObject;
|
||||
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:lastComponent];
|
||||
|
||||
if ([[NSCharacterSet decimalDigitCharacterSet] isSupersetOfSet:set]) {
|
||||
tempSuffix = [lastComponent integerValue];
|
||||
|
||||
// -1 for space.
|
||||
NSInteger index = tempBase.length - lastComponent.length - 1;
|
||||
tempBase = [tempBase substringToIndex:index];
|
||||
}
|
||||
}
|
||||
tempSuffix++;
|
||||
|
||||
*baseString = tempBase;
|
||||
*suffix = tempSuffix;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,39 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFileBaseOperation.h"
|
||||
|
||||
@protocol OCTFileInputProtocol;
|
||||
|
||||
@interface OCTFileUploadOperation : OCTFileBaseOperation
|
||||
|
||||
@property (strong, nonatomic, readonly, nonnull) id<OCTFileInputProtocol> input;
|
||||
|
||||
/**
|
||||
* Create operation.
|
||||
*
|
||||
* @param fileInput Input to use as a source for file transfer.
|
||||
*
|
||||
* For other parameters description see OCTFileBaseOperation.
|
||||
*/
|
||||
- (nullable instancetype)initWithTox:(nonnull OCTTox *)tox
|
||||
fileInput:(nonnull id<OCTFileInputProtocol>)fileInput
|
||||
friendNumber:(OCTToxFriendNumber)friendNumber
|
||||
fileNumber:(OCTToxFileNumber)fileNumber
|
||||
fileSize:(OCTToxFileSize)fileSize
|
||||
userInfo:(nullable NSDictionary *)userInfo
|
||||
progressBlock:(nullable OCTFileBaseOperationProgressBlock)progressBlock
|
||||
etaUpdateBlock:(nullable OCTFileBaseOperationProgressBlock)etaUpdateBlock
|
||||
successBlock:(nullable OCTFileBaseOperationSuccessBlock)successBlock
|
||||
failureBlock:(nullable OCTFileBaseOperationFailureBlock)failureBlock;
|
||||
|
||||
/**
|
||||
* Call this method to request next chunk.
|
||||
*
|
||||
* @param position The file or stream position from which to continue reading.
|
||||
* @param length The number of bytes requested for the current chunk.
|
||||
*/
|
||||
- (void)chunkRequestWithPosition:(OCTToxFileSize)position length:(size_t)length;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,109 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTFileUploadOperation.h"
|
||||
#import "OCTFileBaseOperation+Private.h"
|
||||
#import "OCTFileInputProtocol.h"
|
||||
#import "OCTLogging.h"
|
||||
#import "NSError+OCTFile.h"
|
||||
|
||||
@interface OCTFileUploadOperation ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTFileUploadOperation
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (nullable instancetype)initWithTox:(nonnull OCTTox *)tox
|
||||
fileInput:(nonnull id<OCTFileInputProtocol>)fileInput
|
||||
friendNumber:(OCTToxFriendNumber)friendNumber
|
||||
fileNumber:(OCTToxFileNumber)fileNumber
|
||||
fileSize:(OCTToxFileSize)fileSize
|
||||
userInfo:(nullable NSDictionary *)userInfo
|
||||
progressBlock:(nullable OCTFileBaseOperationProgressBlock)progressBlock
|
||||
etaUpdateBlock:(nullable OCTFileBaseOperationProgressBlock)etaUpdateBlock
|
||||
successBlock:(nullable OCTFileBaseOperationSuccessBlock)successBlock
|
||||
failureBlock:(nullable OCTFileBaseOperationFailureBlock)failureBlock
|
||||
{
|
||||
NSParameterAssert(fileInput);
|
||||
|
||||
self = [super initWithTox:tox
|
||||
friendNumber:friendNumber
|
||||
fileNumber:fileNumber
|
||||
fileSize:fileSize
|
||||
userInfo:userInfo
|
||||
progressBlock:progressBlock
|
||||
etaUpdateBlock:etaUpdateBlock
|
||||
successBlock:successBlock
|
||||
failureBlock:failureBlock];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_input = fileInput;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)chunkRequestWithPosition:(OCTToxFileSize)position length:(size_t)length
|
||||
{
|
||||
if (length == 0) {
|
||||
[self finishWithSuccess];
|
||||
return;
|
||||
}
|
||||
|
||||
NSData *data = [self.input bytesWithPosition:position length:length];
|
||||
|
||||
if (! data) {
|
||||
[self finishWithError:[NSError sendFileErrorCannotReadFile]];
|
||||
return;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
|
||||
BOOL result;
|
||||
do {
|
||||
result = [self.tox fileSendChunkForFileNumber:self.fileNumber
|
||||
friendNumber:self.friendNumber
|
||||
position:position
|
||||
data:data
|
||||
error:&error];
|
||||
|
||||
if (! result) {
|
||||
[NSThread sleepForTimeInterval:0.01];
|
||||
}
|
||||
}
|
||||
while (! result && error.code == OCTToxErrorFileSendChunkSendq);
|
||||
|
||||
if (! result) {
|
||||
OCTLogWarn(@"upload error %@", error);
|
||||
|
||||
[self.tox fileSendControlForFileNumber:self.fileNumber
|
||||
friendNumber:self.friendNumber
|
||||
control:OCTToxFileControlCancel
|
||||
error:nil];
|
||||
|
||||
[self finishWithError:[NSError acceptFileErrorFromToxFileSendChunkError:error.code]];
|
||||
return;
|
||||
}
|
||||
|
||||
[self updateBytesDone:position + length];
|
||||
}
|
||||
|
||||
#pragma mark - Override
|
||||
|
||||
- (void)operationStarted
|
||||
{
|
||||
[super operationStarted];
|
||||
|
||||
if (! [self.input prepareToRead]) {
|
||||
[self finishWithError:[NSError sendFileErrorCannotReadFile]];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,42 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTToxConstants.h"
|
||||
|
||||
@class OCTTox;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void (^OCTSendMessageOperationSuccessBlock)(OCTToxMessageId messageId);
|
||||
typedef void (^OCTSendMessageOperationFailureBlock)(NSError *error);
|
||||
|
||||
@interface OCTSendMessageOperation : NSOperation
|
||||
|
||||
/**
|
||||
* Create operation.
|
||||
*
|
||||
* @param tox Tox object to send to.
|
||||
* @param friendNumber Number of friend to send to.
|
||||
* @param messageType Type of the message to send.
|
||||
* @param message Message to send.
|
||||
* @param msgv3HashHex the messageV3 Hash Hexstring or nil.
|
||||
* @param successBlock Block called on operation success. Block will be called on main thread.
|
||||
* @param failureBlock Block called on loading error. Block will be called on main thread.
|
||||
*/
|
||||
- (instancetype)initWithTox:(OCTTox *)tox
|
||||
friendNumber:(OCTToxFriendNumber)friendNumber
|
||||
messageType:(OCTToxMessageType)messageType
|
||||
message:(NSString *)message
|
||||
msgv3HashHex:(NSString *)msgv3HashHex
|
||||
msgv3tssec:(UInt32)msgv3tssec
|
||||
successBlock:(nullable OCTSendMessageOperationSuccessBlock)successBlock
|
||||
failureBlock:(nullable OCTSendMessageOperationFailureBlock)failureBlock;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,80 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTSendMessageOperation.h"
|
||||
#import "OCTTox.h"
|
||||
|
||||
@interface OCTSendMessageOperation ()
|
||||
|
||||
@property (weak, nonatomic, readonly) OCTTox *tox;
|
||||
|
||||
@property (assign, nonatomic, readonly) OCTToxFriendNumber friendNumber;
|
||||
@property (assign, nonatomic, readonly) OCTToxMessageType messageType;
|
||||
@property (copy, nonatomic, readonly) NSString *message;
|
||||
@property (copy, nonatomic, readonly) NSString *msgv3HashHex;
|
||||
@property (assign, nonatomic, readonly) UInt32 msgv3tssec;
|
||||
@property (copy, nonatomic, readonly) OCTSendMessageOperationSuccessBlock successBlock;
|
||||
@property (copy, nonatomic, readonly) OCTSendMessageOperationFailureBlock failureBlock;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTSendMessageOperation
|
||||
|
||||
- (instancetype)initWithTox:(OCTTox *)tox
|
||||
friendNumber:(OCTToxFriendNumber)friendNumber
|
||||
messageType:(OCTToxMessageType)messageType
|
||||
message:(NSString *)message
|
||||
msgv3HashHex:(NSString *)msgv3HashHex
|
||||
msgv3tssec:(UInt32)msgv3tssec
|
||||
successBlock:(nullable OCTSendMessageOperationSuccessBlock)successBlock
|
||||
failureBlock:(nullable OCTSendMessageOperationFailureBlock)failureBlock
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_tox = tox;
|
||||
_friendNumber = friendNumber;
|
||||
_messageType = messageType;
|
||||
_message = [message copy];
|
||||
_msgv3HashHex = [msgv3HashHex copy];
|
||||
_msgv3tssec = msgv3tssec;
|
||||
_successBlock = [successBlock copy];
|
||||
_failureBlock = [failureBlock copy];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)main
|
||||
{
|
||||
if (self.cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
|
||||
OCTToxMessageId messageId = [self.tox sendMessageWithFriendNumber:self.friendNumber
|
||||
type:self.messageType
|
||||
message:self.message
|
||||
msgv3HashHex:self.msgv3HashHex
|
||||
msgv3tssec:self.msgv3tssec
|
||||
error:&error];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (error && self.failureBlock) {
|
||||
self.failureBlock(error);
|
||||
}
|
||||
else if (! error && self.successBlock) {
|
||||
self.successBlock(messageId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,8 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTManagerConstants.h"
|
||||
|
||||
NSString *const kOCTManagerErrorDomain = @"me.dvor.objcTox.OCTManagerErrorDomain";
|
||||
@@ -0,0 +1,475 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTManagerFactory.h"
|
||||
#import "OCTManagerImpl.h"
|
||||
#import "OCTManagerConfiguration.h"
|
||||
#import "OCTRealmManager.h"
|
||||
#import "OCTTox.h"
|
||||
#import "OCTToxEncryptSave.h"
|
||||
#import "OCTToxEncryptSaveConstants.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, OCTDecryptionErrorFileType) {
|
||||
OCTDecryptionErrorFileTypeDatabaseKey,
|
||||
OCTDecryptionErrorFileTypeToxFile,
|
||||
};
|
||||
|
||||
static const NSUInteger kEncryptedKeyLength = 64;
|
||||
|
||||
@implementation OCTManagerFactory
|
||||
|
||||
+ (void)managerWithConfiguration:(OCTManagerConfiguration *)configuration
|
||||
encryptPassword:(nonnull NSString *)encryptPassword
|
||||
successBlock:(void (^)(id<OCTManager> manager))successBlock
|
||||
failureBlock:(void (^)(NSError *error))failureBlock
|
||||
{
|
||||
[self validateConfiguration:configuration];
|
||||
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
|
||||
// Decrypting Realm.
|
||||
__block NSData *realmEncryptionKey = nil;
|
||||
__block NSError *decryptRealmError = nil;
|
||||
|
||||
dispatch_group_async(group, queue, ^{
|
||||
realmEncryptionKey = [self realmEncryptionKeyWithConfiguration:configuration
|
||||
password:encryptPassword
|
||||
error:&decryptRealmError];
|
||||
});
|
||||
|
||||
|
||||
// Decrypting Tox save.
|
||||
__block NSError *decryptToxError = nil;
|
||||
__block OCTToxEncryptSave *encryptSave = nil;
|
||||
__block NSData *toxSave = nil;
|
||||
|
||||
dispatch_group_async(group, queue, ^{
|
||||
if (! [self importToxSaveIfNeeded:configuration error:&decryptToxError]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSData *savedData = [self getSavedDataFromPath:configuration.fileStorage.pathForToxSaveFile];
|
||||
|
||||
encryptSave = [self toxEncryptSaveWithToxPassword:encryptPassword savedData:savedData error:&decryptToxError];
|
||||
|
||||
if (! encryptSave) {
|
||||
return;
|
||||
}
|
||||
|
||||
savedData = [self decryptSavedData:savedData encryptSave:encryptSave error:&decryptToxError];
|
||||
|
||||
if (! savedData) {
|
||||
return;
|
||||
}
|
||||
|
||||
toxSave = savedData;
|
||||
});
|
||||
|
||||
dispatch_async(queue, ^{
|
||||
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSError *error = decryptRealmError ?: decryptToxError;
|
||||
|
||||
if (error) {
|
||||
if (failureBlock) {
|
||||
failureBlock(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
OCTTox *tox = [self createToxWithOptions:configuration.options toxData:toxSave error:&error];
|
||||
|
||||
if (! tox) {
|
||||
if (failureBlock) {
|
||||
failureBlock(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL *databaseFileURL = [NSURL fileURLWithPath:configuration.fileStorage.pathForDatabase];
|
||||
OCTRealmManager *realmManager = [[OCTRealmManager alloc] initWithDatabaseFileURL:databaseFileURL encryptionKey:realmEncryptionKey];
|
||||
|
||||
OCTManagerImpl *manager = [[OCTManagerImpl alloc] initWithConfiguration:configuration
|
||||
tox:tox
|
||||
toxEncryptSave:encryptSave
|
||||
realmManager:realmManager];
|
||||
|
||||
if (successBlock) {
|
||||
successBlock(manager);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
+ (void)validateConfiguration:(OCTManagerConfiguration *)configuration
|
||||
{
|
||||
NSParameterAssert(configuration.fileStorage);
|
||||
NSParameterAssert(configuration.fileStorage.pathForDownloadedFilesDirectory);
|
||||
NSParameterAssert(configuration.fileStorage.pathForUploadedFilesDirectory);
|
||||
NSParameterAssert(configuration.fileStorage.pathForTemporaryFilesDirectory);
|
||||
|
||||
NSParameterAssert(configuration.options);
|
||||
}
|
||||
|
||||
+ (NSData *)realmEncryptionKeyWithConfiguration:(OCTManagerConfiguration *)configuration
|
||||
password:(NSString *)databasePassword
|
||||
error:(NSError **)error
|
||||
{
|
||||
NSString *databasePath = configuration.fileStorage.pathForDatabase;
|
||||
NSString *encryptedKeyPath = configuration.fileStorage.pathForDatabaseEncryptionKey;
|
||||
|
||||
BOOL databaseExists = [[NSFileManager defaultManager] fileExistsAtPath:databasePath];
|
||||
BOOL encryptedKeyExists = [[NSFileManager defaultManager] fileExistsAtPath:encryptedKeyPath];
|
||||
|
||||
if (! databaseExists && ! encryptedKeyExists) {
|
||||
// First run, create key and database.
|
||||
if (! [self createEncryptedKeyAtPath:encryptedKeyPath withPassword:databasePassword]) {
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorDatabaseKeyCannotCreateKey];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
if (databaseExists && ! encryptedKeyExists) {
|
||||
// It seems that we found old unencrypted database, let's migrate to encrypted one.
|
||||
NSError *migrationError;
|
||||
|
||||
BOOL result = [self migrateToEncryptedDatabase:databasePath
|
||||
encryptionKeyPath:encryptedKeyPath
|
||||
withPassword:databasePassword
|
||||
error:&migrationError];
|
||||
|
||||
if (! result) {
|
||||
if (error) {
|
||||
*error = [NSError errorWithDomain:kOCTManagerErrorDomain code:OCTManagerInitErrorDatabaseKeyMigrationToEncryptedFailed userInfo:@{
|
||||
NSLocalizedDescriptionKey : migrationError.localizedDescription,
|
||||
NSLocalizedFailureReasonErrorKey : migrationError.localizedFailureReason,
|
||||
}];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
NSData *encryptedKey = [NSData dataWithContentsOfFile:encryptedKeyPath];
|
||||
|
||||
if (! encryptedKey) {
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorDatabaseKeyCannotReadKey];
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSError *decryptError;
|
||||
NSData *key = [OCTToxEncryptSave decryptData:encryptedKey withPassphrase:databasePassword error:&decryptError];
|
||||
|
||||
if (! key) {
|
||||
[self fillError:error withDecryptionError:decryptError.code fileType:OCTDecryptionErrorFileTypeDatabaseKey];
|
||||
return nil;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
+ (BOOL)createEncryptedKeyAtPath:(NSString *)path withPassword:(NSString *)password
|
||||
{
|
||||
NSMutableData *key = [NSMutableData dataWithLength:kEncryptedKeyLength];
|
||||
SecRandomCopyBytes(kSecRandomDefault, key.length, (uint8_t *)key.mutableBytes);
|
||||
|
||||
NSData *encryptedKey = [OCTToxEncryptSave encryptData:key withPassphrase:password error:nil];
|
||||
|
||||
return [encryptedKey writeToFile:path options:NSDataWritingAtomic error:nil];
|
||||
}
|
||||
|
||||
+ (BOOL)fillError:(NSError **)error withDecryptionError:(OCTToxEncryptSaveDecryptionError)code fileType:(OCTDecryptionErrorFileType)fileType
|
||||
{
|
||||
if (! error) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSDictionary *mapping;
|
||||
|
||||
switch (fileType) {
|
||||
case OCTDecryptionErrorFileTypeDatabaseKey:
|
||||
mapping = @{
|
||||
@(OCTToxEncryptSaveDecryptionErrorNull) : @(OCTManagerInitErrorDatabaseKeyDecryptNull),
|
||||
@(OCTToxEncryptSaveDecryptionErrorBadFormat) : @(OCTManagerInitErrorDatabaseKeyDecryptBadFormat),
|
||||
@(OCTToxEncryptSaveDecryptionErrorFailed) : @(OCTManagerInitErrorDatabaseKeyDecryptFailed),
|
||||
};
|
||||
break;
|
||||
case OCTDecryptionErrorFileTypeToxFile:
|
||||
mapping = @{
|
||||
@(OCTToxEncryptSaveDecryptionErrorNull) : @(OCTManagerInitErrorToxFileDecryptNull),
|
||||
@(OCTToxEncryptSaveDecryptionErrorBadFormat) : @(OCTManagerInitErrorToxFileDecryptBadFormat),
|
||||
@(OCTToxEncryptSaveDecryptionErrorFailed) : @(OCTManagerInitErrorToxFileDecryptFailed),
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
OCTManagerInitError initErrorCode = [mapping[@(code)] integerValue];
|
||||
[self fillError:error withInitErrorCode:initErrorCode];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)fillError:(NSError **)error withInitErrorCode:(OCTManagerInitError)code
|
||||
{
|
||||
if (! error) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *failureReason = nil;
|
||||
|
||||
switch (code) {
|
||||
case OCTManagerInitErrorPassphraseFailed:
|
||||
failureReason = @"Cannot create symmetric key from given passphrase.";
|
||||
break;
|
||||
case OCTManagerInitErrorCannotImportToxSave:
|
||||
failureReason = @"Cannot copy tox save at `importToxSaveFromPath` path.";
|
||||
break;
|
||||
case OCTManagerInitErrorDatabaseKeyCannotCreateKey:
|
||||
failureReason = @"Cannot create encryption key.";
|
||||
break;
|
||||
case OCTManagerInitErrorDatabaseKeyCannotReadKey:
|
||||
failureReason = @"Cannot read encryption key.";
|
||||
break;
|
||||
case OCTManagerInitErrorDatabaseKeyMigrationToEncryptedFailed:
|
||||
// Nothing to do here, this error will be created elsewhere.
|
||||
break;
|
||||
case OCTManagerInitErrorDatabaseKeyDecryptNull:
|
||||
failureReason = @"Cannot decrypt database key file. Some input data was empty.";
|
||||
break;
|
||||
case OCTManagerInitErrorDatabaseKeyDecryptBadFormat:
|
||||
failureReason = @"Cannot decrypt database key file. Data has bad format.";
|
||||
break;
|
||||
case OCTManagerInitErrorDatabaseKeyDecryptFailed:
|
||||
failureReason = @"Cannot decrypt database key file. The encrypted byte array could not be decrypted. Either the data was corrupt or the password/key was incorrect.";
|
||||
break;
|
||||
case OCTManagerInitErrorToxFileDecryptNull:
|
||||
failureReason = @"Cannot decrypt tox save file. Some input data was empty.";
|
||||
break;
|
||||
case OCTManagerInitErrorToxFileDecryptBadFormat:
|
||||
failureReason = @"Cannot decrypt tox save file. Data has bad format.";
|
||||
break;
|
||||
case OCTManagerInitErrorToxFileDecryptFailed:
|
||||
failureReason = @"Cannot decrypt tox save file. The encrypted byte array could not be decrypted. Either the data was corrupt or the password/key was incorrect.";
|
||||
break;
|
||||
case OCTManagerInitErrorCreateToxUnknown:
|
||||
failureReason = @"Cannot create tox. Unknown error occurred.";
|
||||
break;
|
||||
case OCTManagerInitErrorCreateToxMemoryError:
|
||||
failureReason = @"Cannot create tox. Was unable to allocate enough memory to store the internal structures for the Tox object.";
|
||||
break;
|
||||
case OCTManagerInitErrorCreateToxPortAlloc:
|
||||
failureReason = @"Cannot create tox. Was unable to bind to a port.";
|
||||
break;
|
||||
case OCTManagerInitErrorCreateToxProxyBadType:
|
||||
failureReason = @"Cannot create tox. Proxy type was invalid.";
|
||||
break;
|
||||
case OCTManagerInitErrorCreateToxProxyBadHost:
|
||||
failureReason = @"Cannot create tox. proxyAddress had an invalid format or was nil (while proxyType was set).";
|
||||
break;
|
||||
case OCTManagerInitErrorCreateToxProxyBadPort:
|
||||
failureReason = @"Cannot create tox. Proxy port was invalid.";
|
||||
break;
|
||||
case OCTManagerInitErrorCreateToxProxyNotFound:
|
||||
failureReason = @"Cannot create tox. The proxy host passed could not be resolved.";
|
||||
break;
|
||||
case OCTManagerInitErrorCreateToxEncrypted:
|
||||
failureReason = @"Cannot create tox. The saved data to be loaded contained an encrypted save.";
|
||||
break;
|
||||
case OCTManagerInitErrorCreateToxBadFormat:
|
||||
failureReason = @"Cannot create tox. Data has bad format.";
|
||||
break;
|
||||
}
|
||||
|
||||
*error = [NSError errorWithDomain:kOCTManagerErrorDomain code:code userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Cannot create OCTManager",
|
||||
NSLocalizedFailureReasonErrorKey : failureReason
|
||||
}];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)migrateToEncryptedDatabase:(NSString *)databasePath
|
||||
encryptionKeyPath:(NSString *)encryptionKeyPath
|
||||
withPassword:(NSString *)password
|
||||
error:(NSError **)error
|
||||
{
|
||||
NSParameterAssert(databasePath);
|
||||
NSParameterAssert(encryptionKeyPath);
|
||||
NSParameterAssert(password);
|
||||
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:encryptionKeyPath]) {
|
||||
if (error) {
|
||||
*error = [NSError errorWithDomain:kOCTManagerErrorDomain code:100 userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Cannot migrate unencrypted database to encrypted",
|
||||
NSLocalizedFailureReasonErrorKey : @"Database is already encrypted",
|
||||
}];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *tempKeyPath = [encryptionKeyPath stringByAppendingPathExtension:@"tmp"];
|
||||
|
||||
if (! [self createEncryptedKeyAtPath:tempKeyPath withPassword:password]) {
|
||||
if (error) {
|
||||
*error = [NSError errorWithDomain:kOCTManagerErrorDomain code:101 userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Cannot migrate unencrypted database to encrypted",
|
||||
NSLocalizedFailureReasonErrorKey : @"Cannot create encryption key",
|
||||
}];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSData *encryptedKey = [NSData dataWithContentsOfFile:tempKeyPath];
|
||||
|
||||
if (! encryptedKey) {
|
||||
if (error) {
|
||||
*error = [NSError errorWithDomain:kOCTManagerErrorDomain code:102 userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Cannot migrate unencrypted database to encrypted",
|
||||
NSLocalizedFailureReasonErrorKey : @"Cannot find encryption key",
|
||||
}];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSData *key = [OCTToxEncryptSave decryptData:encryptedKey withPassphrase:password error:error];
|
||||
|
||||
if (! key) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (! [OCTRealmManager migrateToEncryptedDatabase:databasePath encryptionKey:key error:error]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (! [[NSFileManager defaultManager] moveItemAtPath:tempKeyPath toPath:encryptionKeyPath error:error]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)importToxSaveIfNeeded:(OCTManagerConfiguration *)configuration error:(NSError **)error
|
||||
{
|
||||
BOOL result = YES;
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
if (configuration.importToxSaveFromPath && [fileManager fileExistsAtPath:configuration.importToxSaveFromPath]) {
|
||||
result = [fileManager copyItemAtPath:configuration.importToxSaveFromPath
|
||||
toPath:configuration.fileStorage.pathForToxSaveFile
|
||||
error:nil];
|
||||
}
|
||||
|
||||
if (! result) {
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorCannotImportToxSave];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (OCTToxEncryptSave *)toxEncryptSaveWithToxPassword:(NSString *)toxPassword
|
||||
savedData:(NSData *)savedData
|
||||
error:(NSError **)error
|
||||
{
|
||||
OCTToxEncryptSave *encryptSave;
|
||||
|
||||
if (savedData && [OCTToxEncryptSave isDataEncrypted:savedData]) {
|
||||
encryptSave = [[OCTToxEncryptSave alloc] initWithPassphrase:toxPassword toxData:savedData error:nil];
|
||||
}
|
||||
else {
|
||||
// Save data wasn't encrypted. Passing nil as toxData parameter to encrypt it next time.
|
||||
encryptSave = [[OCTToxEncryptSave alloc] initWithPassphrase:toxPassword toxData:nil error:nil];
|
||||
}
|
||||
|
||||
if (! encryptSave) {
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorPassphraseFailed];
|
||||
return nil;
|
||||
}
|
||||
|
||||
return encryptSave;
|
||||
}
|
||||
|
||||
+ (NSData *)decryptSavedData:(NSData *)data encryptSave:(OCTToxEncryptSave *)encryptSave error:(NSError **)error
|
||||
{
|
||||
NSParameterAssert(encryptSave);
|
||||
|
||||
if (! data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
if (! [OCTToxEncryptSave isDataEncrypted:data]) {
|
||||
// Tox data wasn't encrypted, nothing to do here.
|
||||
return data;
|
||||
}
|
||||
|
||||
NSError *decryptError = nil;
|
||||
|
||||
NSData *result = [encryptSave decryptData:data error:&decryptError];
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
[self fillError:error withDecryptionError:decryptError.code fileType:OCTDecryptionErrorFileTypeToxFile];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSData *)getSavedDataFromPath:(NSString *)path
|
||||
{
|
||||
return [[NSFileManager defaultManager] fileExistsAtPath:path] ?
|
||||
([NSData dataWithContentsOfFile:path]) :
|
||||
nil;
|
||||
}
|
||||
|
||||
+ (OCTTox *)createToxWithOptions:(OCTToxOptions *)options toxData:(NSData *)toxData error:(NSError **)error
|
||||
{
|
||||
NSError *toxError = nil;
|
||||
|
||||
OCTTox *tox = [[OCTTox alloc] initWithOptions:options savedData:toxData error:&toxError];
|
||||
|
||||
if (tox) {
|
||||
return tox;
|
||||
}
|
||||
|
||||
OCTToxErrorInitCode code = toxError.code;
|
||||
|
||||
switch (code) {
|
||||
case OCTToxErrorInitCodeUnknown:
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorCreateToxUnknown];
|
||||
break;
|
||||
case OCTToxErrorInitCodeMemoryError:
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorCreateToxMemoryError];
|
||||
break;
|
||||
case OCTToxErrorInitCodePortAlloc:
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorCreateToxPortAlloc];
|
||||
break;
|
||||
case OCTToxErrorInitCodeProxyBadType:
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorCreateToxProxyBadType];
|
||||
break;
|
||||
case OCTToxErrorInitCodeProxyBadHost:
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorCreateToxProxyBadHost];
|
||||
break;
|
||||
case OCTToxErrorInitCodeProxyBadPort:
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorCreateToxProxyBadPort];
|
||||
break;
|
||||
case OCTToxErrorInitCodeProxyNotFound:
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorCreateToxProxyNotFound];
|
||||
break;
|
||||
case OCTToxErrorInitCodeEncrypted:
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorCreateToxEncrypted];
|
||||
break;
|
||||
case OCTToxErrorInitCodeLoadBadFormat:
|
||||
[self fillError:error withInitErrorCode:OCTManagerInitErrorCreateToxBadFormat];
|
||||
break;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,27 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OCTManager.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class OCTManagerConfiguration;
|
||||
@class OCTTox;
|
||||
@class OCTToxEncryptSave;
|
||||
@class OCTRealmManager;
|
||||
|
||||
@interface OCTManagerImpl : NSObject <OCTManager>
|
||||
|
||||
- (instancetype)initWithConfiguration:(OCTManagerConfiguration *)configuration
|
||||
tox:(OCTTox *)tox
|
||||
toxEncryptSave:(OCTToxEncryptSave *)toxEncryptSave
|
||||
realmManager:(OCTRealmManager *)realmManager;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user