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
|
||||
|
Reference in New Issue
Block a user