netSerial

serializer producing compact bitstreams
git clone https://noulin.net/git/netSerial.git
Log | Files | Refs | README | LICENSE

commit b5103027386a74d2b929689d2f74f4541e2b0b76
parent 94e2e6ea19317dc809ba386684a7569b5d65f42c
Author: Remy Noulin <loader2x@gmail.com>
Date:   Sat, 13 Oct 2018 20:30:16 +0200

add netSerial level 0, 1, 2 and 3 (default)

README.md           |  106 +
memTest.c.template  |   23 +
memcheckNetSerial.c | 1537 ++++++++++
netSerial.c         | 5260 +++++++++++++++++++++++++++++++++++
netSerial.c.gcov    | 7713 +++++++++++++++++++++++++++++++++++++++++++++++++++
netSerial.h         |  106 +
netSerialInternal.h |   61 +
package.yml         |   28 +
runMemtest.c        |  108 +
test.c              |   95 +
testNetSerial.c     | 1565 +++++++++++
testNetSerial.sh    |    5 +
testNetSerialMem.sh |    2 +
13 files changed, 16609 insertions(+)

Diffstat:
AREADME.md | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AmemTest.c.template | 24++++++++++++++++++++++++
AmemcheckNetSerial.c | 1537+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AnetSerial.c | 5260+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AnetSerial.c.gcov | 7713+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AnetSerial.h | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AnetSerialInternal.h | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage.yml | 28++++++++++++++++++++++++++++
ArunMemtest.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AtestNetSerial.c | 1565+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AtestNetSerial.sh | 5+++++
AtestNetSerialMem.sh | 3+++
13 files changed, 16612 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md @@ -0,0 +1,106 @@ +# Sheepy +This is a sheepy package for [sheepy](https://github.com/RemyNoulin/sheepy) and using [libsheepy](https://github.com/RemyNoulin/libsheepy) + +# netSerial + +netSerial is a serializer/deserializer for JSON data structures that has compact binary format. + +In general, it gives smaller bitstreams than JSON strings and smallJson serializer bitstream. + +The netSerial serializer is in average 1.5 times slower than the smallJson serializer. + +# Usage + +Install with spm: `spm install netSerial` + +Include netSerial: `#include "shpPackages/netSerial/netSerial.h"`, then: + +```c +// create a netSerial object: +createNetSerial(n); + +// create a JSON +parseG(&n, "[3,270,-86942]"); + +smallBytest *bitstream = serialG(&n); +``` + +# Encoding + +Data types are encoding on 4 bits: +- undefined +- bool +- dict +- double +- varint +- string +- array +- bytes = faststring +- packed dict +- packed double +- packed varint +- packed string +- packed array +- packed bytes +- dict - all elements have same type +- array - all elements have same type + +Integers are encoded as varint (n <<1 ^ n >> 63, see [protobuf](https://developers.google.com/protocol-buffers/docs/encoding)) and lengths (array, dictionary) are encoded as varuint. + +The integer _150_ is encoded as `0xc4 0x25`. + +- 0xc_4_ is integer type +- 0x_c_4 are the first 3 bits in 150, bit 7 is set so next byte represents the 7 next bits in 150 +- _0x25_ are last bits in 150 + +The encoding of `[3,270,-86942]` gives: +``` +0x4f - uniform array of varint elements +0x03 - 3 elements +0x06 - int 3 +0x9c 0x04 - int 270 +0xbb 0xce 0x0a - int -86942 +``` + +The arrays have 2 variants: normal and uniform. + +Normal arrays have elements of any types whereas uniform arrays have only one type of elements. + +For example, `[null,null,null]` is an uniform array of undefined values, encoded as: +``` +0x0f - uniform array of undefined(null) elements +0x03 - 3 elements +``` + +undefined is a type without data, only the element count is needed to represent an array of null elements. + +The bool type is encoded in 4bits type + 1 bit data and are packed by default: + +``` +{"sdf":true,"0":null,"1":null,"2":true,"3":true} + +0x52 - dictionary with 5 elements +0x73 0x64 0x66 0x00 - "sdf" string +0x71 - bool type and bool data for bool 1,2 and 3 (true) +0x30 0x00 - "0" string +0x00 - undefined 1 and 2 +0x31 0x00 - "1" string +0x32 0x00 - "2" string +0x11 - bool type 2 and 3 +0x33 0x00 - "3" string +``` + +Encoding a dictionary and an array: +``` +{"a":[3,270,-86942]} + +0xfe - uniform dictionary of uniform arrays +0x01 - 1 element +0x61 0x00 - "a" string +0x34 - int type and 3 elements +0x06 - int 3 +0x9c 0x04 - int 270 +0xbb 0xce 0x0a - int -86942 +``` + +- diff --git a/memTest.c.template b/memTest.c.template @@ -0,0 +1,23 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define ck_assert_str_eq(a,b) a;b; +#define ck_assert_str_ne(a,b) a;b; +#define ck_assert_ptr_eq(a,b) a;b; +#define ck_assert_ptr_ne(a,b) a;b; +#define ck_assert_uint_eq(a,b) a;b; +#define ck_assert_uint_ne(a,b) a;b; +#define ck_assert_int_eq(a,b) a;b; +#define ck_assert_int_ne(a,b) a;b; +#define ck_assert(a) a; + +__tests + +int main(int n, char**v) { + +initLibsheepy(v[0]); +setLogMode(LOG_FUNC); + +__calls +}+ \ No newline at end of file diff --git a/memcheckNetSerial.c b/memcheckNetSerial.c @@ -0,0 +1,1537 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define ck_assert_str_eq(a,b) a;b; +#define ck_assert_str_ne(a,b) a;b; +#define ck_assert_ptr_eq(a,b) a;b; +#define ck_assert_ptr_ne(a,b) a;b; +#define ck_assert_uint_eq(a,b) a;b; +#define ck_assert_uint_ne(a,b) a;b; +#define ck_assert_int_eq(a,b) a;b; +#define ck_assert_int_ne(a,b) a;b; +#define ck_assert(a) a; + + +#include "libsheepyObject.h" +#include "netSerial.h" + +int argc; char **argv; + +/* enable/disable logging */ +/* #undef pLog */ +/* #define pLog(...) */ + + +void topT(void) { + + // STEPS + // init + // init allocate + // terminate + // allocate + // string + // duplicate + + createNetSerial(n); + createNetSerial(ds); + char *s; + smallBytest *B; + createSmallDict(d); + createSmallArray(a); + + // undefined + undefinedt *oU = allocUndefined(); + setTopNFreeG(&n, (baset *)oU); + B = serialG(&n); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "null"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // bool + setTopG(&n, TRUE); + B = serialG(&n); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[17]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "true"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // double + setTopG(&n, 1.2); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s", toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[3,51,51,51,51,51,51,-13,63]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "1.200000e+00"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // int + setTopG(&n, 120); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[-12,30]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "120"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // string + setTopG(&n, "string"); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[5,115,116,114,105,110,103,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "string"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // dict + setG(&d, "k", 4); + setTopG(&n, &d); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[78,1,107,0,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"k\":4}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // array + pushG(&a, "k"); + pushG(&a, 4); + setTopG(&n, &a); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[38,69,107,0,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[\"k\",4]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + +} + + + +void uniformDictT(void) { + + // STEPS + // init + // init allocate + // terminate + // allocate + // string + // duplicate + + createNetSerial(n); + createNetSerial(ds); + char *s; + smallBytest *B; + createSmallDict(d); + createSmallDict(dd); + createSmallArray(a); + + // undefined + undefinedt *oU = allocUndefined(); + setG(&d, "0", oU); + setG(&d, "1", oU); + setG(&d, "2", oU); + setG(&d, "3", oU); + setG(&d, "4", oU); + setNFreeG(&d, "5", oU); + setTopG(&n, &d); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[14,6,48,0,49,0,50,0,51,0,52,0,53,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":null,\"1\":null,\"2\":null,\"3\":null,\"4\":null,\"5\":null}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // empty dict + initiateG(&d); + setTopG(&n, &d); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[14,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // bool + initiateG(&d); + setG(&d, "0", TRUE); + setG(&d, "1", TRUE); + setG(&d, "2", TRUE); + setG(&d, "3", TRUE); + setTopG(&n, &d); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[30,4,48,0,15,49,0,50,0,51,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":true,\"1\":true,\"2\":true,\"3\":true}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // 9 bools + initiateG(&d); + setG(&d, "0", TRUE); + setG(&d, "1", TRUE); + setG(&d, "2", TRUE); + setG(&d, "3", TRUE); + setG(&d, "4", TRUE); + setG(&d, "5", TRUE); + setG(&d, "6", TRUE); + setG(&d, "7", TRUE); + setG(&d, "8", TRUE); + setTopG(&n, &d); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[30,9,48,0,-1,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,1]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":true,\"1\":true,\"2\":true,\"3\":true,\"4\":true,\"5\":true,\"6\":true,\"7\":true,\"8\":true}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + + // double + initiateG(&d); + setG(&d, "0", 1.1); + setG(&d, "1", 2.2); + setG(&d, "2", 3.3); + setTopG(&n, &d); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[62,3,48,0,-10,-10,-10,-10,-10,-10,-15,63,49,0,-10,-10,-10,-10,-10,-10,1,64,50,0,102,102,102,102,102,102,10,64]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":1.100000e+00,\"1\":2.200000e+00,\"2\":3.300000e+00}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // int + initiateG(&d); + setG(&d, "0", 1); + setG(&d, "1", 2); + setTopG(&n, &d); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[78,2,48,0,2,49,0,4]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":1,\"1\":2}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // string + initiateG(&d); + setG(&d, "0", "a"); + setG(&d, "1", "A"); + setG(&d, "2", "z"); + setTopG(&n, &d); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[94,3,48,0,97,0,49,0,65,0,50,0,122,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":\"a\",\"1\":\"A\",\"2\":\"z\"}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // dict + initiateG(&d); + setG(&dd, "9", "z"); + setG(&dd, "1", 1); + setG(&d, "0", &dd); + initiateG(&dd); + setG(&dd, "Z", "-"); + setG(&dd, "A", 234); + setG(&d, "1", &dd); + setTopG(&n, &d); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[46,2,48,0,2,57,0,69,122,0,49,0,2,49,0,2,90,0,69,45,0,65,0,-44,3]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":{\"9\":\"z\",\"1\":1},\"1\":{\"Z\":\"-\",\"A\":234}}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // uniform dict + initiateG(&dd); + initiateG(&d); + setG(&dd, "9", 1); + setG(&dd, "1", 2); + setG(&d, "0", &dd); + initiateG(&dd); + setG(&dd, "Z", "-"); + setG(&dd, "A", "+"); + setG(&d, "1", &dd); + setTopG(&n, &d); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[-18,2,48,0,36,57,0,2,49,0,4,49,0,37,90,0,45,0,65,0,43,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":{\"9\":1,\"1\":2},\"1\":{\"Z\":\"-\",\"A\":\"+\"}}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // array + initiateG(&d); + pushG(&a, "k"); + pushG(&a, 4); + setG(&d, "0", &a); + setTopG(&n, &d); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[110,1,48,0,2,69,107,0,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":[\"k\",4]}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // uniform array + initiateG(&d); + initiateG(&a); + pushG(&a, 1); + pushG(&a, 2); + pushG(&a, 3); + pushG(&a, 4); + setG(&d, "0", &a); + setTopG(&n, &d); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[-2,1,48,0,68,2,4,6,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":[1,2,3,4]}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + +} + + +// uniformArray +void uniformArrayT(void) { + + // STEPS + // init + // init allocate + // terminate + // allocate + // string + // duplicate + + createNetSerial(n); + createNetSerial(ds); + char *s; + smallBytest *B; + createSmallArray(A); + createSmallDict(dd); + createSmallArray(a); + + // undefined + undefinedt *oU = allocUndefined(); + pushG(&A, oU); + pushG(&A, oU); + pushG(&A, oU); + pushG(&A, oU); + pushG(&A, oU); + pushNFreeG(&A, oU); + setTopG(&n, &A); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[15,6]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[null,null,null,null,null,null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // empty dict + initiateG(&A); + setTopG(&n, &A); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[15,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // bool + initiateG(&A); + pushG(&A, TRUE); + pushG(&A, TRUE); + pushG(&A, TRUE); + pushG(&A, TRUE); + setTopG(&n, &A); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[31,4,15]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[true,true,true,true]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // double + initiateG(&A); + pushG(&A, 1.1); + pushG(&A, 2.2); + pushG(&A, 3.3); + setTopG(&n, &A); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[63,3,-10,-10,-10,-10,-10,-10,-15,63,-10,-10,-10,-10,-10,-10,1,64,102,102,102,102,102,102,10,64]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[1.100000e+00,2.200000e+00,3.300000e+00]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // int + initiateG(&A); + pushG(&A, 1); + pushG(&A, 2); + setTopG(&n, &A); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[79,2,2,4]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[1,2]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // string + initiateG(&A); + pushG(&A, "a"); + pushG(&A, "A"); + pushG(&A, "z"); + setTopG(&n, &A); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[95,3,97,0,65,0,122,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[\"a\",\"A\",\"z\"]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // dict + initiateG(&A); + setG(&dd, "9", "z"); + setG(&dd, "1", 1); + pushG(&A, &dd); + initiateG(&dd); + setG(&dd, "Z", "-"); + setG(&dd, "A", 234); + pushG(&A, &dd); + setTopG(&n, &A); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[47,2,2,57,0,69,122,0,49,0,2,2,90,0,69,45,0,65,0,-44,3]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[{\"9\":\"z\",\"1\":1},{\"Z\":\"-\",\"A\":234}]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // uniform dict + initiateG(&dd); + initiateG(&A); + setG(&dd, "9", 1); + setG(&dd, "1", 2); + pushG(&A, &dd); + initiateG(&dd); + setG(&dd, "Z", "-"); + setG(&dd, "A", "+"); + pushG(&A, &dd); + setTopG(&n, &A); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[-17,2,36,57,0,2,49,0,4,37,90,0,45,0,65,0,43,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[{\"9\":1,\"1\":2},{\"Z\":\"-\",\"A\":\"+\"}]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // array + initiateG(&A); + pushG(&a, "k"); + pushG(&a, 4); + pushG(&A, &a); + setTopG(&n, &A); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[111,1,2,69,107,0,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[[\"k\",4]]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + initiateG(&A); + initiateG(&a); + pushG(&a, 1); + pushG(&a, 2); + pushG(&a, 3); + pushG(&a, 4); + pushG(&A, &a); + setTopG(&n, &A); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[-1,1,68,2,4,6,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[[1,2,3,4]]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // many bools in uniform array + parseG(&n, "[true,true,true,true,true,true,true,true,false,true]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[31,10,-1,2]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[true,true,true,true,true,true,true,true,false,true]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + +} + + +// dict with values, dict, array, uniforms, packed test high/low nibbles +void dictT(void) { + + // STEPS + // init + // init allocate + // terminate + // allocate + // string + // duplicate + + createNetSerial(n); + createNetSerial(ds); + char *s; + smallBytest *B; + createSmallDict(d); + createSmallDict(dd); + createSmallArray(a); + + // null and uniform dict + initiateG(&d); + setG(&d, "0", NULL); + initiateG(&dd); + setG(&dd, "Z", "-"); + setG(&dd, "A", "+"); + setG(&d, "1", &dd); + setTopG(&n, &d); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[34,48,0,-32,49,0,37,90,0,45,0,65,0,43,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":null,\"1\":{\"Z\":\"-\",\"A\":\"+\"}}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // null and dict + initiateG(&d); + setG(&d, "0", NULL); + initiateG(&dd); + setG(&dd, "Z", "-"); + setG(&dd, "A", 1); + setG(&d, "1", &dd); + setTopG(&n, &d); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[34,48,0,32,49,0,2,90,0,69,45,0,65,0,2]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":null,\"1\":{\"Z\":\"-\",\"A\":1}}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // bool and uniform dict + initiateG(&d); + setG(&d, "0", TRUE); + initiateG(&dd); + setG(&dd, "Z", "-"); + setG(&dd, "A", "+"); + setG(&d, "1", &dd); + setTopG(&n, &d); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[34,48,0,17,49,0,94,2,90,0,45,0,65,0,43,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":true,\"1\":{\"Z\":\"-\",\"A\":\"+\"}}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // null element and uniform array + initiateG(&d); + setG(&d, "1", NULL); + initiateG(&a); + pushG(&a, 1); + pushG(&a, 2); + pushG(&a, 3); + pushG(&a, 4); + setG(&d, "0", &a); + setTopG(&n, &d); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[34,49,0,-16,48,0,68,2,4,6,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"1\":null,\"0\":[1,2,3,4]}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // uniform array high nibble + initiateG(&d); + setG(&d, "1", TRUE); + initiateG(&a); + pushG(&a, 1); + pushG(&a, 2); + pushG(&a, 3); + pushG(&a, 4); + setG(&d, "0", &a); + setTopG(&n, &d); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[34,49,0,17,48,0,79,4,2,4,6,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"1\":true,\"0\":[1,2,3,4]}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // uniform array in high nibble + initiateG(&d); + setG(&d, "1", "1"); + initiateG(&a); + pushG(&a, 1); + pushG(&a, 2); + pushG(&a, 3); + pushG(&a, 4); + setG(&d, "0", &a); + setTopG(&n, &d); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[34,49,0,-11,49,0,48,0,68,2,4,6,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"1\":\"1\",\"0\":[1,2,3,4]}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // low and high nibble undefined + parseG(&n, "{"_"0"_":null,"_"1"_":null, "_"2"_":1}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[50,48,0,0,49,0,50,0,36]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":null,\"1\":null,\"2\":1}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // low and high nibble bool + parseG(&n, "{"_"z"_":null,"_"0"_":true,"_"1"_":true, "_"2"_":true, "_"3"_":true"_"4"_":true"_"5"_":true, "_"6"_":true, "_"7"_":true, "_"8"_":true, "_"9"_":true, "_"a"_":true, "_"b"_":true, "_"c"_":true, "_"d"_":true}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[-14,1,122,0,16,48,0,-1,49,0,17,50,0,51,0,17,52,0,53,0,17,54,0,55,0,17,56,0,63,57,0,17,97,0,98,0,17,99,0,100,0,1]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"z\":null,\"0\":true,\"1\":true,\"2\":true,\"3\":true,\"4\":true,\"5\":true,\"6\":true,\"7\":true,\"8\":true,\"9\":true,\"a\":true,\"b\":true,\"c\":true,\"d\":true}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // low and high nibble bool - deserialDict ctx->nibble == lowNbl and ctx->boolShift == 8 + parseG(&n, "{"_"z"_":null,"_"0"_":true,"_"1"_":true, "_"2"_":true, "_"3"_":true, "_"4"_":true, "_"5"_":true, "_"6"_":true, "_"7"_":true, \"Z\": null, "_"8"_":true, "_"9"_":true, "_"a"_":true, "_"b"_":true, "_"c"_":true, "_"d"_":true}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[-12,2,122,0,16,48,0,-1,49,0,17,50,0,51,0,17,52,0,53,0,17,54,0,55,0,1,90,0,56,0,-15,57,0,17,97,0,98,0,17,99,0,3,100,0,1]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"z\":null,\"0\":true,\"1\":true,\"2\":true,\"3\":true,\"4\":true,\"5\":true,\"6\":true,\"7\":true,\"Z\":null,\"8\":true,\"9\":true,\"a\":true,\"b\":true,\"c\":true,\"d\":true}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // dict in dict + parseG(&n, "{"_"0"_":{\"0\":true}, "_"2"_":{\"0\":false},\"z\":null}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[50,48,0,30,1,48,0,1,50,0,30,1,48,0,122,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":{\"0\":true},\"2\":{\"0\":false},\"z\":null}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + + // low and high nibble double + parseG(&n, "{"_"0"_":0.0, "_"2"_":2.0,\"z\":null}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[50,48,0,51,0,0,0,0,0,0,0,0,50,0,0,0,0,0,0,0,0,64,122,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":0.000000e+00,\"2\":2.000000e+00,\"z\":null}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble string + parseG(&n, "{"_"0"_":null, "_"2"_":\"2.0\",\"z\":null}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[50,48,0,80,50,0,50,46,48,0,122,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":null,\"2\":\"2.0\",\"z\":null}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // array in dict + parseG(&n, "{"_"0"_":null, "_"2"_":[1,2],\"z\":[true,3]}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[50,48,0,-16,50,0,36,2,4,122,0,38,17,100]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":null,\"2\":[1,2],\"z\":[true,3]}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + + + // packed dicts + parseG(&n, "{"_"0"_":{},"_"1"_":{}, "_"2"_":{}, "_"3"_":{}, "_"4"_":{}, "_"5"_": 1}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[98,48,0,88,0,49,0,0,50,0,0,51,0,0,52,0,0,53,0,36]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":{},\"1\":{},\"2\":{},\"3\":{},\"4\":{},\"5\":1}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + parseG(&n, "{"_"0"_":{"_"0"_":null,"_"1"_":1},"_"1"_":{"_"0"_":"_"0"_","_"1"_":1}, "_"2"_":{"_"0"_":"_"0"_","_"1"_":1}, "_"3"_":{"_"0"_":"_"0"_","_"1"_":1}, "_"4"_":{"_"0"_":"_"0"_","_"1"_":1}, "_"5"_": 1}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[98,48,0,88,2,48,0,64,49,0,2,49,0,2,48,0,69,48,0,49,0,2,50,0,2,48,0,69,48,0,49,0,2,51,0,2,48,0,69,48,0,49,0,2,52,0,2,48,0,69,48,0,49,0,2,53,0,36]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":{\"0\":null,\"1\":1},\"1\":{\"0\":\"0\",\"1\":1},\"2\":{\"0\":\"0\",\"1\":1},\"3\":{\"0\":\"0\",\"1\":1},\"4\":{\"0\":\"0\",\"1\":1},\"5\":1}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble packed dicts + parseG(&n, "{\"a\": null,"_"0"_":{},"_"1"_":{}, "_"2"_":{}, "_"3"_":{}, "_"4"_":{}, "_"5"_": 1}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[114,97,0,-12,48,0,5,0,49,0,0,50,0,0,51,0,0,52,0,0,53,0,36]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"a\":null,\"0\":{},\"1\":{},\"2\":{},\"3\":{},\"4\":{},\"5\":1}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + + // packed doubles + parseG(&n, "{"_"0"_":0.0,"_"1"_":1.0, "_"2"_":2.0, "_"3"_":3.0, "_"4"_":4.0, "_"5"_": null}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[98,48,0,89,0,0,0,0,0,0,0,0,49,0,0,0,0,0,0,0,-16,63,50,0,0,0,0,0,0,0,0,64,51,0,0,0,0,0,0,0,8,64,52,0,0,0,0,0,0,0,16,64,53,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":0.000000e+00,\"1\":1.000000e+00,\"2\":2.000000e+00,\"3\":3.000000e+00,\"4\":4.000000e+00,\"5\":null}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble packed doubles + parseG(&n, "{\"a\": null, "_"0"_":0.0,"_"1"_":1.0, "_"2"_":2.0, "_"3"_":3.0, "_"4"_":4.0, "_"5"_": null}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[114,97,0,-11,48,0,5,0,0,0,0,0,0,0,0,49,0,0,0,0,0,0,0,-16,63,50,0,0,0,0,0,0,0,0,64,51,0,0,0,0,0,0,0,8,64,52,0,0,0,0,0,0,0,16,64,53,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"a\":null,\"0\":0.000000e+00,\"1\":1.000000e+00,\"2\":2.000000e+00,\"3\":3.000000e+00,\"4\":4.000000e+00,\"5\":null}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + + // packed ints + parseG(&n, "{\"1\":1,\"2\":2,\"3\":3,\"4\":4,\"Z\":\"l\"}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[82,49,0,74,2,50,0,4,51,0,6,52,0,8,90,0,5,108,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"1\":1,\"2\":2,\"3\":3,\"4\":4,\"Z\":\"l\"}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble packed ints + parseG(&n, "{\"0\":null,\"1\":1,\"2\":2,\"3\":3,\"4\":4,\"Z\":\"l\"}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[98,48,0,-96,49,0,4,2,50,0,4,51,0,6,52,0,8,90,0,5,108,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":null,\"1\":1,\"2\":2,\"3\":3,\"4\":4,\"Z\":\"l\"}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + + // packed strings + parseG(&n, "{\"1\":\"1\",\"2\":\"2\",\"3\":\"3\",\"4\":\"4\",\"Z\":null}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[82,49,0,75,49,0,50,0,50,0,51,0,51,0,52,0,52,0,90,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"1\":\"1\",\"2\":\"2\",\"3\":\"3\",\"4\":\"4\",\"Z\":null}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble packed strings + parseG(&n, "{\"0\":null,\"1\":\"1\",\"2\":\"2\",\"3\":\"3\",\"4\":\"4\",\"Z\":null}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[98,48,0,-80,49,0,4,49,0,50,0,50,0,51,0,51,0,52,0,52,0,90,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":null,\"1\":\"1\",\"2\":\"2\",\"3\":\"3\",\"4\":\"4\",\"Z\":null}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // packed arrays + parseG(&n, "{\"1\":[],\"2\":[1],\"3\":[\"3r\"],\"4\":[true],\"Z\":null}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[82,49,0,76,0,50,0,1,36,51,0,1,21,51,114,0,52,0,1,1,90,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"1\":[],\"2\":[1],\"3\":[\"3r\"],\"4\":[true],\"Z\":null}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble packed arrays + parseG(&n, "{\"0\":null,\"1\":[],\"2\":[1],\"3\":[\"3r\"],\"4\":[true],\"Z\":null}"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[98,48,0,-64,49,0,4,0,50,0,1,36,51,0,1,21,51,114,0,52,0,1,1,90,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "{\"0\":null,\"1\":[],\"2\":[1],\"3\":[\"3r\"],\"4\":[true],\"Z\":null}"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + +} + + +// array with values, dict, array, uniforms, packed test high/low nibbles +void arrayT(void) { + + // STEPS + // init + // init allocate + // terminate + // allocate + // string + // duplicate + + createNetSerial(n); + createNetSerial(ds); + char *s; + smallBytest *B; + createSmallArray(A); + createSmallArray(a); + + // null and uniform array + initiateG(&A); + pushG(&A, NULL); + initiateG(&a); + pushG(&a, 1); + pushG(&a, 2); + pushG(&a, 3); + pushG(&a, 4); + pushG(&A, &a); + setTopG(&n, &A); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[38,-16,68,2,4,6,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + //ck_assert_str_eq(s, "[null,null]"); + ck_assert_str_eq(s, "[null,[1,2,3,4]]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // uniform array in high low + initiateG(&A); + pushG(&A, FALSE); + initiateG(&a); + pushG(&a, 1); + pushG(&a, 2); + pushG(&a, 3); + pushG(&a, 4); + pushG(&A, &a); + setTopG(&n, &A); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[38,1,79,4,2,4,6,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + //ck_assert_str_eq(s, "[null,null]"); + ck_assert_str_eq(s, "[false,[1,2,3,4]]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // uniform array in high nibble + initiateG(&A); + pushG(&A, "1"); + initiateG(&a); + pushG(&a, 1); + pushG(&a, 2); + pushG(&a, 3); + pushG(&a, 4); + pushG(&A, &a); + setTopG(&n, &A); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[38,-11,49,0,68,2,4,6,8]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[\"1\",[1,2,3,4]]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble array + parseG(&n, "[null, [1,null]]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[38,96,2,36,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[null,[1,null]]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // low and high undefined + parseG(&n, "[null,null,1]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[54,0,36]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[null,null,1]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // low and high nibble bool + parseG(&n, "[null,true,false,false,true,true,false,true,false,true,true,true,true,true]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[-26,1,16,89,17,17,17,17,31,17,17]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[null,true,false,false,true,true,false,true,false,true,true,true,true,true]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // low and high nibble bool - ctx->boolOffset != 0 ctx->nibble == lowNbl ctx->boolShift == 8 + parseG(&n, "[true,false,false,true,null,true,false,true,false,true,true,true,true,true]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[-26,1,-11,17,1,81,17,17,31,17,17]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[true,false,false,true,null,true,false,true,false,true,true,true,true,true]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + + // dict in array + parseG(&n, "[{\"0\":null,\"1\":1},{\"2\":2},{\"3\":3},null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[70,34,48,0,64,49,0,2,78,1,50,0,4,78,1,51,0,6,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[{\"0\":null,\"1\":1},{\"2\":2},{\"3\":3},null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // double in array + parseG(&n, "[1.0,2.0,null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[54,51,0,0,0,0,0,0,-16,63,0,0,0,0,0,0,0,64,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[1.000000e+00,2.000000e+00,null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // int in array + parseG(&n, "[1,2,null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[54,36,68,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[1,2,null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // string in array + parseG(&n, "[\"1\",\"2\",null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[54,85,49,0,50,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[\"1\",\"2\",null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // array in array + parseG(&n, "[[],[1,2],null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[54,15,0,79,2,2,4,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[[],[1,2],null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + + // packed dicts + parseG(&n, "[{\"1\":1},{\"2\":2},{\"3\":3},{\"4\":4},null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[86,72,1,49,0,36,1,50,0,68,1,51,0,100,1,52,0,-12,1,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[{\"1\":1},{\"2\":2},{\"3\":3},{\"4\":4},null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble packed dicts + parseG(&n, "[null,{\"1\":1},{\"2\":2},{\"3\":3},{\"4\":4},null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[102,-12,4,1,49,0,36,1,50,0,68,1,51,0,100,1,52,0,-12,1,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[null,{\"1\":1},{\"2\":2},{\"3\":3},{\"4\":4},null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // packed doubles + parseG(&n, "[1.0,2.0,3.0,4.0,null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[86,73,0,0,0,0,0,0,-16,63,0,0,0,0,0,0,0,64,0,0,0,0,0,0,8,64,0,0,0,0,0,0,16,64,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[1.000000e+00,2.000000e+00,3.000000e+00,4.000000e+00,null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble packed doubles + parseG(&n, "[null,1.0,2.0,3.0,4.0,null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[102,-11,4,0,0,0,0,0,0,-16,63,0,0,0,0,0,0,0,64,0,0,0,0,0,0,8,64,0,0,0,0,0,0,16,64,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[null,1.000000e+00,2.000000e+00,3.000000e+00,4.000000e+00,null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // packed ints + parseG(&n, "[1,2,3,4,null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[86,74,2,4,6,8,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[1,2,3,4,null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble packed ints + parseG(&n, "[null,1,2,3,4,null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[102,-96,4,2,4,6,8,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[null,1,2,3,4,null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // packed strings + parseG(&n, "[\"1\",\"2\",\"3\",\"4\",null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[86,75,49,0,50,0,51,0,52,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[\"1\",\"2\",\"3\",\"4\",null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble packed strings + parseG(&n, "[null,\"1\",\"2\",\"3\",\"4\",null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[102,-80,4,49,0,50,0,51,0,52,0,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[null,\"1\",\"2\",\"3\",\"4\",null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // packed arrays + parseG(&n, "[[1],[2],[3],[4],null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[86,76,1,36,1,68,1,100,1,-12,1,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[[1],[2],[3],[4],null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + // high nibble packed arrays + parseG(&n, "[null,[1],[2],[3],[4],null]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[102,-64,4,1,36,1,68,1,100,1,-12,1,0]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[null,[1],[2],[3],[4],null]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + +} + + +void variousT(void) { + + createNetSerial(n); + createNetSerial(ds); + char *s; + smallBytest *B; + + + // array dict int bool string + parseG(&n, "[0, \"asd\", {\"rpc\":\"ds\", \"id\":1, \"p\":true}, [true, \"user\", [[false,\"name\",1], [true, \"name2\", 12340], [false, \"zxc\", 234]]]]"); + logVarG(&n); + B = serialG(&n); + logI("len %u", lenG(B)); + logSI("%s",toHexSepS(getValG(B), lenG(B), " ")); + s = sToString((smallt *) B->B); + ck_assert_str_eq(s, "[70,4,37,97,115,100,0,3,114,112,99,0,69,100,115,0,105,100,0,2,112,0,-79,54,81,117,115,101,114,0,111,3,3,81,110,97,109,101,0,36,3,81,110,97,109,101,50,0,-12,-11,24,3,1,69,122,120,99,0,-44,3]"); + free(s); + deserialG(&ds, B); + s = toStringG(&ds); + ck_assert_str_eq(s, "[0,\"asd\",{\"rpc\":\"ds\",\"id\":1,\"p\":true},[true,\"user\",[[false,\"name\",1],[true,\"name2\",12340],[false,\"zxc\",234]]]]"); + free(s); + terminateG(B); + freeManyG(&n, &ds); + + +} + + +int main(int n, char**v) { + +initLibsheepy(v[0]); +setLogMode(LOG_FUNC); + +topT(); +uniformDictT(); +uniformArrayT(); +dictT(); +arrayT(); +variousT(); +} diff --git a/netSerial.c b/netSerial.c @@ -0,0 +1,5260 @@ + +#include "libsheepyObject.h" +#include "netSerial.h" +#include "netSerialInternal.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#define lv logVarG + +void initiateNetSerialLevel0(smallJsont *self); +void initiateNetSerialLevel1(smallJsont *self); +void initiateNetSerialLevel2(smallJsont *self); +void initiateNetSerial(smallJsont *self); +void registerMethodsNetSerialLevel0(smallJsonFunctionst *f); +void registerMethodsNetSerialLevel1(smallJsonFunctionst *f); +void registerMethodsNetSerialLevel2(smallJsonFunctionst *f); +void registerMethodsNetSerial(smallJsonFunctionst *f); +void initiateAllocateNetSerialLevel0(smallJsont **self); +void initiateAllocateNetSerialLevel1(smallJsont **self); +void initiateAllocateNetSerialLevel2(smallJsont **self); +void initiateAllocateNetSerial(smallJsont **self); +void finalizeNetSerial(void); +smallJsont* allocNetSerialLevel0(void); +smallJsont* allocNetSerialLevel1(void); +smallJsont* allocNetSerialLevel2(void); +smallJsont* allocNetSerial(void); +internal const char* helpNetSerial(smallJsont *self); +internal smallBytest* serialNetSerialLevel0(smallJsont *self); +internal smallBytest* serialNetSerialLevel1(smallJsont *self); +internal smallBytest* serialNetSerialLevel2(smallJsont *self); +internal smallBytest* serialNetSerial(smallJsont *self); +internal smallJsont* deserialNetSerialLevel0(smallJsont *self, smallBytest *data); +internal smallJsont* deserialNetSerialLevel1(smallJsont *self, smallBytest *data); +internal smallJsont* deserialNetSerialLevel2(smallJsont *self, smallBytest *data); +internal smallJsont* deserialNetSerial(smallJsont *self, smallBytest *data); + +internal void uintToNetTypeVarint(sBytest **buf, u8 type, u64 value); +internal void uintToVarint(sBytest **buf, u64 value); +internal u64 netTypeVarintToUint(u8 **buf); +internal u64 varintToUint(u8 **buf); + +internal sBytest* netSerialLevel0(smallt *o); +internal void dictNetSerialLevel0(sBytest **r, sDictt *dict); +internal void arrayNetSerialLevel0(sBytest **r, sArrayt *array); +internal sBytest* netSerialLevel1(smallt *o); +internal void dictNetSerialLevel1(sBytest **r, sDictt *dict, contextt *ctx); +internal void arrayNetSerialLevel1(sBytest **r, sArrayt *array, contextt *ctx); +internal sBytest* netSerialLevel2(smallt *o); +internal void dictNetSerialLevel2(sBytest **r, sDictt *dict, contextt *ctx, bool packed); +internal void arrayNetSerialLevel2(sBytest **r, sArrayt *array, contextt *ctx, bool packed); +internal sBytest* netSerial(smallt *o); +internal void dictNetSerial(sBytest **r, sDictt *dict, contextt *ctx, packingT packing); +internal void arrayNetSerial(sBytest **r, sArrayt *array, contextt *ctx, packingT packing); + +internal smallt* netDeserialLevel0(sBytest *obj); +internal void dictNetDeserialLevel0(sDictt **dict, char **data); +internal void arrayNetDeserialLevel0(sArrayt **array, char **data); +internal smallt* netDeserialLevel1(sBytest *obj); +internal void dictNetDeserialLevel1(sDictt **dict, u8 **data, contextt *ctx); +internal void arrayNetDeserialLevel1(sArrayt **array, u8 **data, contextt *ctx); +internal smallt* netDeserialLevel2(sBytest *obj); +internal void dictNetDeserialLevel2(sDictt **dict, u8 **data, contextt *ctx, bool packed); +internal u8 isDictUniform(sDictt *dict); +internal u8 isArrayUniform(sArrayt *array); +internal void uniformDictNetDeserialLevel2(sDictt **dict, u8 **data, contextt *ctx, bool packed); +internal void arrayNetDeserialLevel2(sArrayt **array, u8 **data, contextt *ctx, bool packed); +internal void uniformArrayNetDeserialLevel2(sArrayt **array, u8 **data, contextt *ctx, bool packed); +internal smallt* netDeserial(sBytest *obj); +internal void dictNetDeserial(sDictt **dict, u8 **data, contextt *ctx, bool packed); +internal void uniformDictNetDeserial(sDictt **dict, u8 **data, contextt *ctx, bool packed); +internal void arrayNetDeserial(sArrayt **array, u8 **data, contextt *ctx, bool packed); +internal void uniformArrayNetDeserial(sArrayt **array, u8 **data, contextt *ctx, bool packed); + +/* enable/disable logging */ +/* #undef pLog */ +/* #define pLog(...) */ + +void initiateNetSerialLevel0(smallJsont *self) { + + initiateSmallJson(self); + + self->type = "netSerial"; + if (!netSerialF) { + netSerialF = malloc(sizeof(smallJsonFunctionst)); + registerMethodsNetSerialLevel0(netSerialF); + pErrorNot0(atexit(finalizeNetSerial)); + } + self->f = netSerialF; +} + +void initiateNetSerialLevel1(smallJsont *self) { + + initiateSmallJson(self); + + self->type = "netSerial"; + if (!netSerialF) { + netSerialF = malloc(sizeof(smallJsonFunctionst)); + registerMethodsNetSerialLevel1(netSerialF); + pErrorNot0(atexit(finalizeNetSerial)); + } + self->f = netSerialF; +} + +void initiateNetSerialLevel2(smallJsont *self) { + + initiateSmallJson(self); + + self->type = "netSerial"; + if (!netSerialF) { + netSerialF = malloc(sizeof(smallJsonFunctionst)); + registerMethodsNetSerialLevel2(netSerialF); + pErrorNot0(atexit(finalizeNetSerial)); + } + self->f = netSerialF; +} + +void initiateNetSerial(smallJsont *self) { + + initiateSmallJson(self); + + self->type = "netSerial"; + if (!netSerialF) { + netSerialF = malloc(sizeof(smallJsonFunctionst)); + registerMethodsNetSerial(netSerialF); + pErrorNot0(atexit(finalizeNetSerial)); + } + self->f = netSerialF; +} + +void registerMethodsNetSerialLevel0(smallJsonFunctionst *f) { + + registerMethodsSmallJson(f); + f->help = helpNetSerial; + f->serial = serialNetSerialLevel0; + f->deserial = deserialNetSerialLevel0; +} + +void registerMethodsNetSerialLevel1(smallJsonFunctionst *f) { + + registerMethodsSmallJson(f); + f->help = helpNetSerial; + f->serial = serialNetSerialLevel1; + f->deserial = deserialNetSerialLevel1; +} + +void registerMethodsNetSerialLevel2(smallJsonFunctionst *f) { + + registerMethodsSmallJson(f); + f->help = helpNetSerial; + f->serial = serialNetSerialLevel2; + f->deserial = deserialNetSerialLevel2; +} + +void registerMethodsNetSerial(smallJsonFunctionst *f) { + + registerMethodsSmallJson(f); + f->help = helpNetSerial; + f->serial = serialNetSerial; + f->deserial = deserialNetSerial; +} + +void initiateAllocateNetSerialLevel0(smallJsont **self) { + + if (self) { + (*self) = malloc(sizeof(smallJsont)); + if (*self) { + initiateNetSerialLevel0(*self); + } + } +} + +void initiateAllocateNetSerialLevel1(smallJsont **self) { + + if (self) { + (*self) = malloc(sizeof(smallJsont)); + if (*self) { + initiateNetSerialLevel1(*self); + } + } +} + +void initiateAllocateNetSerialLevel2(smallJsont **self) { + + if (self) { + (*self) = malloc(sizeof(smallJsont)); + if (*self) { + initiateNetSerialLevel2(*self); + } + } +} + +void initiateAllocateNetSerial(smallJsont **self) { + + if (self) { + (*self) = malloc(sizeof(smallJsont)); + if (*self) { + initiateNetSerial(*self); + } + } +} + +void finalizeNetSerial(void) { + + if (netSerialF) { + free(netSerialF); + netSerialF = NULL; + } +} + +smallJsont* allocNetSerialLevel0(void) { + smallJsont *r = NULL; + + initiateAllocateNetSerialLevel0(&r); + ret r; +} + +smallJsont* allocNetSerialLevel1(void) { + smallJsont *r = NULL; + + initiateAllocateNetSerialLevel1(&r); + ret r; +} + +smallJsont* allocNetSerialLevel2(void) { + smallJsont *r = NULL; + + initiateAllocateNetSerialLevel2(&r); + ret r; +} + +smallJsont* allocNetSerial(void) { + smallJsont *r = NULL; + + initiateAllocateNetSerial(&r); + ret r; +} + + +internal const char* helpNetSerial(smallJsont UNUSED *self) { + ret "TODO helpNetSerial \n" helpTextSmallJson; +} + +/** + * encode type in lower nibble, uint value in high nibble and next bytes as varuint + */ +internal void uintToNetTypeVarint(sBytest **buf, u8 type, u64 value) { + u64 c = value; + /* encode b0..2 */ + u8 b = type + ((c & 0x7) << 4); + if (c & 0xFFFFFFFFFFFFFFF8) { + b |= 0x80; + sBytesPush(buf, b); + c >>=3; + /* encode b3..9 ...*/ + while(c) { + b = c & 0x7F; + if (c & 0xFFFFFFFFFFFFFF80) + b |= 0x80; + sBytesPush(buf, b); + c >>=7; + } + } + else + sBytesPush(buf, b); +} + +/** + * encode uint as varuint + */ +internal void uintToVarint(sBytest **buf, u64 value) { + u64 c = value; + u8 b = c & 0x7F; + if (c & 0xFFFFFFFFFFFFFF80) { + b |= 0x80; + sBytesPush(buf, b); + c >>=7; + /* encode b7..14 ...*/ + while(c) { + b = c & 0x7F; + if (c & 0xFFFFFFFFFFFFFF80) + b |= 0x80; + sBytesPush(buf, b); + c >>=7; + } + } + else + sBytesPush(buf, b); +} + +/** + * decode type and varuint to uint + */ +internal u64 netTypeVarintToUint(u8 **buf) { + u64 r = 0; + + r = (**buf >> 4) & 0x7; + + u8 c = 0; + while (**buf & 0x80) { + (*buf)++; + r |= (**buf & 0x7F) << (7*c+3); + c++; + } + (*buf)++; + ret r; +} + +/** + * decode varuint to uint + */ +internal u64 varintToUint(u8 **buf) { + u64 r = 0; + + r = (**buf) & 0x7F; + u8 c = 1; + while (**buf & 0x80) { + (*buf)++; + r |= (**buf & 0x7F) << (7*c); + c++; + } + (*buf)++; + ret r; +} + +// ------------------------------------- +// Serializers + +// level 0 +// like smallJson with ints and length encoded as varints + +/** + * serializer top function + */ +internal sBytest* netSerialLevel0(smallt *o) { + sBytest *r = NULL; + sBytest *B = NULL; + + switch(o->type) { + case UNDEFINED: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + break; + case BOOL: { + u8 c = NET_SERIAL_TYPES[(u8)o->type]; + // set bit 4 when true + if (((sBoolt *)&(o->type))->value) + c |= (1<<4); + sBytesPush(&r, c); + } + break; + case CONTAINER: + // undefined + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + break; + case DICT: + dictNetSerialLevel0(&r, (sDictt *)&(o->type)); + break; + case DOUBLE: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + sBytesPushBuffer(&r, &((sDoublet *)&(o->type))->value, sizeof(double)); + break; + case INT: { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)&(o->type))->value; + // encode v with arithmetic shifts + uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], (v << 1) ^ (v >> 63)); + } + break; + case STRING: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + sBytesPushBuffer(&r, &((sStringt *)&(o->type))->data, sizeof(sStringt) + strlen(&(((sStringt *)&(o->type))->data)) -1); + break; + case ARRAY: + arrayNetSerialLevel0(&r, (sArrayt *)&(o->type)); + break; + case BYTES: + B = (sBytest *)&(o->type); + uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], B->count); + sBytesPushBuffer(&r, &(B->data), B->count); + break; + } + ret r; +} + +/** + * serialize dictionary + * + * the serialized dict is pushed to r. + * All elements are serialized recursively + * + * the data in containers is not serialized + * + * \param + * r small bytes object + * dict dictionary to serialize + */ +internal void dictNetSerialLevel0(sBytest **r, sDictt *dict) { + sBytest *B = NULL; + + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)dict->type], dict->count); + + forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + + switch(e->data->type) { + case UNDEFINED: + sBytesPush(r, NET_SERIAL_TYPES[(u8)e->data->type]); + break; + case BOOL: { + u8 c = NET_SERIAL_TYPES[(u8)e->data->type]; + // set bit 4 when true + if (((sBoolt *)(e->data))->value) + c |= (1<<4); + sBytesPush(r, c); + } + break; + case CONTAINER: + // undefined + sBytesPush(r, NET_SERIAL_TYPES[(u8)e->data->type]); + break; + case DICT: + dictNetSerialLevel0(r, (sDictt *)(e->data)); + break; + case DOUBLE: + sBytesPush(r, NET_SERIAL_TYPES[(u8)e->data->type]); + sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); + break; + case INT: { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)(e->data))->value; + // encode v with arithmetic shifts + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], (v << 1) ^ (v >> 63)); + } + break; + case STRING: + sBytesPush(r, NET_SERIAL_TYPES[(u8)e->data->type]); + sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); + break; + case ARRAY: + arrayNetSerialLevel0(r, (sArrayt *)(e->data)); + break; + case BYTES: + B = (sBytest *)(e->data); + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], B->count); + sBytesPushBuffer(r, &(B->data), B->count); + break; + } + } + } + ret; +} + +/** + * serialize array + * + * the serialized array is pushed to r. + * All elements are serialized recursively + * + * the data in containers is not serialized + * + * \param + * r small bytes object + * array to serialize + */ +internal void arrayNetSerialLevel0(sBytest **r, sArrayt *array) { + sBytest *B = NULL; + + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)array->type], array->count); + + forEachSArray(array, e) { + if (!e) { + // empty slots are represented as undefined elements + sBytesPush(r, NET_SERIAL_TYPES[UNDEFINED]); + } + else { + switch(e->type) { + case UNDEFINED: + sBytesPush(r, NET_SERIAL_TYPES[(u8)e->type]); + break; + case BOOL: { + u8 c = NET_SERIAL_TYPES[(u8)e->type]; + // set bit 4 when true + if (((sBoolt *)&(e->type))->value) + c |= (1<<4); + sBytesPush(r, c); + } + break; + case CONTAINER: + // undefined + sBytesPush(r, NET_SERIAL_TYPES[(u8)e->type]); + break; + case DICT: + dictNetSerialLevel0(r, (sDictt *)e); + break; + case DOUBLE: + sBytesPush(r, NET_SERIAL_TYPES[(u8)e->type]); + sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); + break; + case INT: { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)&(e->type))->value; + // encode v with arithmetic shifts + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], (v << 1) ^ (v >> 63)); + } + break; + case STRING: + sBytesPush(r, NET_SERIAL_TYPES[(u8)e->type]); + sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); + break; + case ARRAY: + arrayNetSerialLevel0(r, (sArrayt *)e); + break; + case BYTES: + B = (sBytest *)e; + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], B->count); + sBytesPushBuffer(r, &(B->data), B->count); + break; + } + } + } + ret; +} + +internal smallBytest* serialNetSerialLevel0(smallJsont *self) { + + smallt *o = getsoG(self); + + if (o == NULL) + ret NULL; + + sBytest *B = netSerialLevel0(o); + + if (!B) { + ret NULL; + } + + createAllocateSmallBytes(r); + r->B = B; + ret r; +} + +// level 1 +// like level 0 with type encoded in nibbles and bools are packed + +/** + * serializer top function + */ +internal sBytest* netSerialLevel1(smallt *o) { + sBytest *r = NULL; + sBytest *B = NULL; + contextt ctx = {.nibble=lowNbl, .nblOffset=0, .boolShift = 0, .boolOffset=0}; + + switch(o->type) { + case UNDEFINED: + case CONTAINER: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + break; + case BOOL: { + u8 c = NET_SERIAL_TYPES[(u8)o->type]; + // set bit 4 when true + if (((sBoolt *)&(o->type))->value) + c |= (1<<4); + sBytesPush(&r, c); + } + break; + case DICT: + dictNetSerialLevel1(&r, (sDictt *)&(o->type), &ctx); + break; + case DOUBLE: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + sBytesPushBuffer(&r, &((sDoublet *)&(o->type))->value, sizeof(double)); + break; + case INT: { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)&(o->type))->value; + // encode v with arithmetic shifts + uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], (v << 1) ^ (v >> 63)); + } + break; + case STRING: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + sBytesPushBuffer(&r, &((sStringt *)&(o->type))->data, sizeof(sStringt) + strlen(&(((sStringt *)&(o->type))->data)) -1); + break; + case ARRAY: + arrayNetSerialLevel1(&r, (sArrayt *)&(o->type), &ctx); + break; + case BYTES: + B = (sBytest *)&(o->type); + uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], B->count); + sBytesPushBuffer(&r, &(B->data), B->count); + break; + } + ret r; +} + +/** + * serialize dictionary + * + * the serialized dict is pushed to r. + * All elements are serialized recursively + * + * the data in containers is not serialized + * + * \param + * r small bytes object + * dict dictionary to serialize + */ +internal void dictNetSerialLevel1(sBytest **r, sDictt *dict, contextt *ctx) { + sBytest *B = NULL; + char *data = NULL; + + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)dict->type], dict->count); + } + else { + // high nibble + #define storeTypeInHighNbl(o)\ + ctx->nibble = lowNbl;\ + data = (char *)&((*r)->data) + ctx->nblOffset;\ + *data |= NET_SERIAL_TYPES[(u8)o->type] << 4 + storeTypeInHighNbl(dict); + uintToVarint(r, dict->count); + } + + forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + + switch(e->data->type) { + case UNDEFINED: + case CONTAINER: + if (ctx->nibble == lowNbl) { + #define storeTypeOnly(o)\ + sBytesPush(r, NET_SERIAL_TYPES[(u8)o->type]);\ + ctx->nibble = highNbl;\ + ctx->nblOffset = (*r)->count -1 + storeTypeOnly(e->data); + } + else { + storeTypeInHighNbl(e->data); + } + break; + case BOOL: + if (!ctx->boolOffset) { + // new packed bools + if (ctx->nibble == lowNbl) { + #define storeNew4bPackedBool(o)\ + u8 c = NET_SERIAL_TYPES[(u8)o->type];\ + /* set bit 4 when true */\ + if (((sBoolt *)(o))->value)\ + c |= (1<<4);\ + sBytesPush(r, c);\ + ctx->boolShift = 5;\ + ctx->boolOffset = (*r)->count -1 + storeNew4bPackedBool(e->data); + } + else { + // high nibble, next byte is packed bools + storeTypeInHighNbl(e->data); + #define storeNew8bPackedBool(o)\ + u8 c = 0;\ + if (((sBoolt *)(o))->value)\ + c = 1;\ + sBytesPush(r, c);\ + ctx->boolShift = 1;\ + ctx->boolOffset = (*r)->count -1 + storeNew8bPackedBool(e->data); + } + } + else { + // there was a bool before this one, fill bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + // previous packed bool is full + // this byte is the new packed bools + storeNew4bPackedBool(e->data); + } + else { + storeTypeOnly(e->data); + #define storeBool(o)\ + data = (char *)&((*r)->data) + ctx->boolOffset;\ + if (((sBoolt *)(o))->value)\ + *data |= 1 << ctx->boolShift;\ + ctx->boolShift++ + storeBool(e->data); + } + } + else { + // high nibble + storeTypeInHighNbl(e->data); + if (ctx->boolShift == 8) { + // previous packed bool is full + // next byte is the new packed bools + storeNew8bPackedBool(e->data); + } + else { + storeBool(e->data); + } + } + } + break; + case DICT: + dictNetSerialLevel1(r, (sDictt *)(e->data), ctx); + break; + case DOUBLE: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e->data); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + } + sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); + break; + case INT: { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)(e->data))->value; + if (ctx->nibble == lowNbl) { + // encode v with arithmetic shifts + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], (v << 1) ^ (v >> 63)); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + uintToVarint(r, (v << 1) ^ (v >> 63)); + } + } + break; + case STRING: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e->data); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + } + sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); + break; + case ARRAY: + arrayNetSerialLevel1(r, (sArrayt *)(e->data), ctx); + break; + case BYTES: + B = (sBytest *)(e->data); + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], B->count); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + uintToVarint(r, B->count); + } + sBytesPushBuffer(r, &(B->data), B->count); + break; + } + } + } + ret; +} + +/** + * serialize array + * + * the serialized array is pushed to r. + * All elements are serialized recursively + * + * the data in containers is not serialized + * + * \param + * r small bytes object + * array to serialize + */ +internal void arrayNetSerialLevel1(sBytest **r, sArrayt *array, contextt *ctx) { + sBytest *B = NULL; + char *data = NULL; + + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)array->type], array->count); + } + else { + // high nibble + storeTypeInHighNbl(array); + uintToVarint(r, array->count); + } + + forEachSArray(array, e) { + if (!e) { + // empty slots are represented as undefined elements + if (ctx->nibble == lowNbl) { + sBytesPush(r, NET_SERIAL_TYPES[UNDEFINED]); + ctx->nibble = highNbl; + ctx->nblOffset = (*r)->count -1; + } + else { + // high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= NET_SERIAL_TYPES[UNDEFINED] << 4; + } + } + else { + switch(e->type) { + case UNDEFINED: + case CONTAINER: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e); + } + else { + // high nibble + storeTypeInHighNbl(e); + } + break; + case BOOL: + if (!ctx->boolOffset) { + // new packed bools + if (ctx->nibble == lowNbl) { + storeNew4bPackedBool(e); + } + else { + // high nibble, next byte is packed bools + storeTypeInHighNbl(e); + storeNew8bPackedBool(e); + } + } + else { + // there was a bool before this one, fill bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + // previous packed bool is full + // this byte is the new packed bools + storeNew4bPackedBool(e); + } + else { + storeTypeOnly(e); + storeBool(e); + } + } + else { + // high nibble + storeTypeInHighNbl(e); + if (ctx->boolShift == 8) { + // previous packed bool is full + // next byte is the new packed bools + storeNew8bPackedBool(e); + } + else { + storeBool(e); + } + } + } + break; + case DICT: + dictNetSerialLevel1(r, (sDictt *)e, ctx); + break; + case DOUBLE: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e); + } + else { + // high nibble + storeTypeInHighNbl(e); + } + sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); + break; + case INT: { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)&(e->type))->value; + if (ctx->nibble == lowNbl) { + // encode v with arithmetic shifts + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], (v << 1) ^ (v >> 63)); + } + else { + // high nibble + storeTypeInHighNbl(e); + uintToVarint(r, (v << 1) ^ (v >> 63)); + } + } + break; + case STRING: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e); + } + else { + // high nibble + storeTypeInHighNbl(e); + } + sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); + break; + case ARRAY: + arrayNetSerialLevel1(r, (sArrayt *)e, ctx); + break; + case BYTES: + B = (sBytest *)e; + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], B->count); + } + else { + // high nibble + storeTypeInHighNbl(e); + uintToVarint(r, B->count); + } + sBytesPushBuffer(r, &(B->data), B->count); + break; + } + } + } + ret; +} + +internal smallBytest* serialNetSerialLevel1(smallJsont *self) { + + smallt *o = getsoG(self); + + if (o == NULL) + ret NULL; + + sBytest *B = netSerialLevel1(o); + + if (!B) { + ret NULL; + } + + createAllocateSmallBytes(r); + r->B = B; + ret r; +} + +// level 2 +// like level 1, arrays are set to uniform when all elements are same type + +/** + * serializer top function + */ +internal sBytest* netSerialLevel2(smallt *o) { + sBytest *r = NULL; + sBytest *B = NULL; + contextt ctx = {.nibble=lowNbl, .nblOffset=0, .boolShift = 0, .boolOffset=0}; + + switch(o->type) { + case UNDEFINED: + case CONTAINER: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + break; + case BOOL: { + u8 c = NET_SERIAL_TYPES[(u8)o->type]; + // set bit 4 when true + if (((sBoolt *)&(o->type))->value) + c |= (1<<4); + sBytesPush(&r, c); + } + break; + case DICT: + dictNetSerialLevel2(&r, (sDictt *)&(o->type), &ctx, /*packed=*/false); + break; + case DOUBLE: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + sBytesPushBuffer(&r, &((sDoublet *)&(o->type))->value, sizeof(double)); + break; + case INT: { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)&(o->type))->value; + // encode v with arithmetic shifts + uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], (v << 1) ^ (v >> 63)); + } + break; + case STRING: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + sBytesPushBuffer(&r, &((sStringt *)&(o->type))->data, sizeof(sStringt) + strlen(&(((sStringt *)&(o->type))->data)) -1); + break; + case ARRAY: + arrayNetSerialLevel2(&r, (sArrayt *)&(o->type), &ctx, /*packed=*/false); + break; + case BYTES: + B = (sBytest *)&(o->type); + uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], B->count); + sBytesPushBuffer(&r, &(B->data), B->count); + break; + } + ret r; +} + +internal u8 isDictUniform(sDictt *dict) { + bool allElementsHaveSameType = true; + bool foundFirstType = false; + u8 type = 0; + forEachSDict(dict, e) { + if (e->key) { + if (foundFirstType) { + u8 nextType; + switch(e->data->type) { + case DICT: + nextType = isDictUniform((sDictt*)e->data); + break; + case ARRAY: + nextType = isArrayUniform((sArrayt*)e->data); + break; + default: + nextType = NET_SERIAL_TYPES[(u8)e->data->type]; + } + if (nextType != type) { + allElementsHaveSameType = false; + break; + } + } + else { + switch(e->data->type) { + case DICT: + type = isDictUniform((sDictt*)e->data); + break; + case ARRAY: + type = isArrayUniform((sArrayt*)e->data); + break; + default: + type = NET_SERIAL_TYPES[(u8)e->data->type]; + } + foundFirstType = true; + } + } + } + if (allElementsHaveSameType) + type = UNIFORM_DICT; + else + type = S_DICT; + ret type; +} + +internal u8 isArrayUniform(sArrayt *array) { + bool allElementsHaveSameType = true; + bool foundFirstType = false; + char type = 0; + forEachSArray(array, e) { + if (!e) { + if (foundFirstType) { + if (type != S_UNDEFINED) { + allElementsHaveSameType = false; + break; + } + } + else { + type = S_UNDEFINED; + foundFirstType = true; + } + } + else { + if (foundFirstType) { + u8 nextType; + switch(e->type) { + case DICT: + nextType = isDictUniform((sDictt*)e); + break; + case ARRAY: + nextType = isArrayUniform((sArrayt*)e); + break; + default: + nextType = NET_SERIAL_TYPES[(u8)e->type]; + } + if (nextType != type) { + allElementsHaveSameType = false; + break; + } + } + else { + switch(e->type) { + case DICT: + type = isDictUniform((sDictt*)e); + break; + case ARRAY: + type = isArrayUniform((sArrayt*)e); + break; + default: + type = NET_SERIAL_TYPES[(u8)e->type]; + } + foundFirstType = true; + } + } + } + if (allElementsHaveSameType) + type = UNIFORM_ARRAY; + else + type = S_ARRAY; + ret type; +} + +/** + * serialize dictionary + * + * the serialized dict is pushed to r. + * All elements are serialized recursively + * + * the data in containers is not serialized + * + * \param + * r small bytes object + * dict dictionary to serialize + */ +internal void dictNetSerialLevel2(sBytest **r, sDictt *dict, contextt *ctx, bool packed) { + sBytest *B = NULL; + char *data = NULL; + + // check if all elements have same type + bool allElementsHaveSameType = true; + bool foundFirstType = false; + char type = 0; + {forEachSDict(dict, e) { + if (e->key) { + if (foundFirstType) { + u8 nextType; + switch(e->data->type) { + case DICT: + nextType = isDictUniform((sDictt*)e->data); + break; + case ARRAY: + nextType = isArrayUniform((sArrayt*)e->data); + break; + default: + nextType = NET_SERIAL_TYPES[(u8)e->data->type]; + } + if (nextType != type) { + allElementsHaveSameType = false; + break; + } + } + else { + switch(e->data->type) { + case DICT: + type = isDictUniform((sDictt*)e->data); + break; + case ARRAY: + type = isArrayUniform((sArrayt*)e->data); + break; + default: + type = NET_SERIAL_TYPES[(u8)e->data->type]; + } + foundFirstType = true; + } + } + }} + + if (allElementsHaveSameType) { + // pack dictionary + if (packed) { + uintToNetTypeVarint(r, type, dict->count); + } + else { + if (ctx->nibble == lowNbl) { + sBytesPush(r, (type << 4) + UNIFORM_DICT); + uintToVarint(r, dict->count); + } + else { + // high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= UNIFORM_DICT << 4; + uintToNetTypeVarint(r, type, dict->count); + } + } + + switch(type) { + case S_UNDEFINED: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + } + }} + + break; + case S_BOOL: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + + if (!ctx->boolOffset) { + // new packed bools + storeNew8bPackedBool(e->data); + } + else { + // there was a bool before this one, fill bits in nibbles + if (ctx->boolShift == 8) { + // previous packed bool is full + // next byte is the new packed bools + storeNew8bPackedBool(e->data); + } + else { + storeBool(e->data); + } + } + } + }} + break; + case S_DICT: + case UNIFORM_DICT: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + dictNetSerialLevel2(r, (sDictt *)(e->data), ctx, /*packed=*/true); + } + }} + break; + case S_DOUBLE: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); + } + }} + break; + case S_INT: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + i64 v = ((sIntt *)(e->data))->value; + uintToVarint(r, (v << 1) ^ (v >> 63)); + } + }} + break; + case S_STRING: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); + } + }} + break; + case S_ARRAY: + case UNIFORM_ARRAY: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + arrayNetSerialLevel2(r, (sArrayt *)(e->data), ctx, /*packed=*/true); + } + }} + break; + case S_BYTES: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + B = (sBytest *)(e->data); + uintToVarint(r, B->count); + sBytesPushBuffer(r, &(B->data), B->count); + } + }} + break; + } + ret; + } + + if (packed) { + uintToVarint(r, dict->count); + } + else { + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)dict->type], dict->count); + } + else { + // high nibble +#define storeTypeInHighNbl(o)\ + ctx->nibble = lowNbl;\ + data = (char *)&((*r)->data) + ctx->nblOffset;\ + *data |= NET_SERIAL_TYPES[(u8)o->type] << 4 + storeTypeInHighNbl(dict); + uintToVarint(r, dict->count); + } + } + + forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + + switch(e->data->type) { + case UNDEFINED: + case CONTAINER: + if (ctx->nibble == lowNbl) { + #define storeTypeOnly(o)\ + sBytesPush(r, NET_SERIAL_TYPES[(u8)o->type]);\ + ctx->nibble = highNbl;\ + ctx->nblOffset = (*r)->count -1 + storeTypeOnly(e->data); + } + else { + storeTypeInHighNbl(e->data); + } + break; + case BOOL: + if (!ctx->boolOffset) { + // new packed bools + if (ctx->nibble == lowNbl) { + #define storeNew4bPackedBool(o)\ + u8 c = NET_SERIAL_TYPES[(u8)o->type];\ + /* set bit 4 when true */\ + if (((sBoolt *)(o))->value)\ + c |= (1<<4);\ + sBytesPush(r, c);\ + ctx->boolShift = 5;\ + ctx->boolOffset = (*r)->count -1 + storeNew4bPackedBool(e->data); + } + else { + // high nibble, next byte is packed bools + storeTypeInHighNbl(e->data); + #define storeNew8bPackedBool(o)\ + u8 c = 0;\ + if (((sBoolt *)(o))->value)\ + c = 1;\ + sBytesPush(r, c);\ + ctx->boolShift = 1;\ + ctx->boolOffset = (*r)->count -1 + storeNew8bPackedBool(e->data); + } + } + else { + // there was a bool before this one, fill bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + // previous packed bool is full + // this byte is the new packed bools + storeNew4bPackedBool(e->data); + } + else { + storeTypeOnly(e->data); + #define storeBool(o)\ + data = (char *)&((*r)->data) + ctx->boolOffset;\ + if (((sBoolt *)(o))->value)\ + *data |= 1 << ctx->boolShift;\ + ctx->boolShift++ + storeBool(e->data); + } + } + else { + // high nibble + storeTypeInHighNbl(e->data); + if (ctx->boolShift == 8) { + // previous packed bool is full + // next byte is the new packed bools + storeNew8bPackedBool(e->data); + } + else { + storeBool(e->data); + } + } + } + break; + case DICT: + dictNetSerialLevel2(r, (sDictt *)(e->data), ctx, /*packed=*/false); + break; + case DOUBLE: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e->data); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + } + sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); + break; + case INT: { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)(e->data))->value; + if (ctx->nibble == lowNbl) { + // encode v with arithmetic shifts + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], (v << 1) ^ (v >> 63)); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + uintToVarint(r, (v << 1) ^ (v >> 63)); + } + } + break; + case STRING: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e->data); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + } + sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); + break; + case ARRAY: + arrayNetSerialLevel2(r, (sArrayt *)(e->data), ctx, /*packed=*/false); + break; + case BYTES: + B = (sBytest *)(e->data); + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], B->count); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + uintToVarint(r, B->count); + } + sBytesPushBuffer(r, &(B->data), B->count); + break; + } + } + } + ret; +} + +/** + * serialize array + * + * the serialized array is pushed to r. + * All elements are serialized recursively + * + * the data in containers is not serialized + * + * \param + * r small bytes object + * array to serialize + */ +internal void arrayNetSerialLevel2(sBytest **r, sArrayt *array, contextt *ctx, bool packed) { + sBytest *B = NULL; + char *data = NULL; + + // check if all elements have same type + bool allElementsHaveSameType = true; + bool foundFirstType = false; + char type = 0; + + {forEachSArray(array, e) { + if (!e) { + if (foundFirstType) { + if (type != S_UNDEFINED) { + allElementsHaveSameType = false; + break; + } + } + else { + type = S_UNDEFINED; + foundFirstType = true; + } + } + else { + if (foundFirstType) { + u8 nextType; + switch(e->type) { + case DICT: + nextType = isDictUniform((sDictt*)e); + break; + case ARRAY: + nextType = isArrayUniform((sArrayt*)e); + break; + default: + nextType = NET_SERIAL_TYPES[(u8)e->type]; + } + if (nextType != type) { + allElementsHaveSameType = false; + break; + } + } + else { + switch(e->type) { + case DICT: + type = isDictUniform((sDictt*)e); + break; + case ARRAY: + type = isArrayUniform((sArrayt*)e); + break; + default: + type = NET_SERIAL_TYPES[(u8)e->type]; + } + foundFirstType = true; + } + } + }} + + if (allElementsHaveSameType) { + // pack array + if (packed) { + uintToNetTypeVarint(r, type, array->count); + } + else { + if (ctx->nibble == lowNbl) { + sBytesPush(r, (type << 4) + UNIFORM_ARRAY); + uintToVarint(r, array->count); + } + else { + // high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= UNIFORM_ARRAY << 4; + uintToNetTypeVarint(r, type, array->count); + } + } + + switch(type) { + case S_BOOL: + {forEachSArray(array, e) { + if (!ctx->boolOffset) { + // new packed bools + storeNew8bPackedBool(e); + } + else { + // there was a bool before this one, fill bits in nibbles + if (ctx->boolShift == 8) { + // previous packed bool is full + // next byte is the new packed bools + storeNew8bPackedBool(e); + } + else { + storeBool(e); + } + } + }} + break; + case S_DICT: + case UNIFORM_DICT: + {forEachSArray(array, e) { + dictNetSerialLevel2(r, (sDictt *)e, ctx, /*packed=*/true); + }} + break; + case S_DOUBLE: + {forEachSArray(array, e) { + sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); + }} + break; + case S_INT: + {forEachSArray(array, e) { + i64 v = ((sIntt *)e)->value; + uintToVarint(r, (v << 1) ^ (v >> 63)); + }} + break; + case S_STRING: + {forEachSArray(array, e) { + sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); + }} + break; + case S_ARRAY: + case UNIFORM_ARRAY: + {forEachSArray(array, e) { + arrayNetSerialLevel2(r, (sArrayt *)e, ctx, /*packed=*/true); + }} + break; + case S_BYTES: + {forEachSArray(array, e) { + B = (sBytest *)e; + uintToVarint(r, B->count); + sBytesPushBuffer(r, &(B->data), B->count); + }} + break; + } + ret; + } + + if (packed) { + uintToVarint(r, array->count); + } + else { + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)array->type], array->count); + } + else { + // high nibble + storeTypeInHighNbl(array); + uintToVarint(r, array->count); + } + } + + forEachSArray(array, e) { + if (!e) { + // empty slots are represented as undefined elements + if (ctx->nibble == lowNbl) { + sBytesPush(r, NET_SERIAL_TYPES[UNDEFINED]); + ctx->nibble = highNbl; + ctx->nblOffset = (*r)->count -1; + } + else { + // high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= NET_SERIAL_TYPES[UNDEFINED] << 4; + } + } + else { + switch(e->type) { + case UNDEFINED: + case CONTAINER: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e); + } + else { + // high nibble + storeTypeInHighNbl(e); + } + break; + case BOOL: + if (!ctx->boolOffset) { + // new packed bools + if (ctx->nibble == lowNbl) { + storeNew4bPackedBool(e); + } + else { + // high nibble, next byte is packed bools + storeTypeInHighNbl(e); + storeNew8bPackedBool(e); + } + } + else { + // there was a bool before this one, fill bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + // previous packed bool is full + // this byte is the new packed bools + storeNew4bPackedBool(e); + } + else { + storeTypeOnly(e); + storeBool(e); + } + } + else { + // high nibble + storeTypeInHighNbl(e); + if (ctx->boolShift == 8) { + // previous packed bool is full + // next byte is the new packed bools + storeNew8bPackedBool(e); + } + else { + storeBool(e); + } + } + } + break; + case DICT: + dictNetSerialLevel2(r, (sDictt *)e, ctx, /*packed=*/false); + break; + case DOUBLE: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e); + } + else { + // high nibble + storeTypeInHighNbl(e); + } + sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); + break; + case INT: { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)&(e->type))->value; + if (ctx->nibble == lowNbl) { + // encode v with arithmetic shifts + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], (v << 1) ^ (v >> 63)); + } + else { + // high nibble + storeTypeInHighNbl(e); + uintToVarint(r, (v << 1) ^ (v >> 63)); + } + } + break; + case STRING: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e); + } + else { + // high nibble + storeTypeInHighNbl(e); + } + sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); + break; + case ARRAY: + arrayNetSerialLevel2(r, (sArrayt *)e, ctx, /*packed=*/false); + break; + case BYTES: + B = (sBytest *)e; + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], B->count); + } + else { + // high nibble + storeTypeInHighNbl(e); + uintToVarint(r, B->count); + } + sBytesPushBuffer(r, &(B->data), B->count); + break; + } + } + } + ret; +} + +internal smallBytest* serialNetSerialLevel2(smallJsont *self) { + + smallt *o = getsoG(self); + + if (o == NULL) + ret NULL; + + sBytest *B = netSerialLevel2(o); + + if (!B) { + ret NULL; + } + + createAllocateSmallBytes(r); + r->B = B; + ret r; +} + +// level 3 +// like level 2, elements of identical type in a row are packed + +/** + * serializer top function + */ +internal sBytest* netSerial(smallt *o) { + sBytest *r = NULL; + sBytest *B = NULL; + contextt ctx = {.nibble=lowNbl, .nblOffset=0, .boolShift = 0, .boolOffset=0}; + + switch(o->type) { + case UNDEFINED: + case CONTAINER: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + break; + case BOOL: { + u8 c = NET_SERIAL_TYPES[(u8)o->type]; + // set bit 4 when true + if (((sBoolt *)&(o->type))->value) + c |= (1<<4); + sBytesPush(&r, c); + } + break; + case DICT: + dictNetSerial(&r, (sDictt *)&(o->type), &ctx, /*packing=*/NOPACKING); + break; + case DOUBLE: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + sBytesPushBuffer(&r, &((sDoublet *)&(o->type))->value, sizeof(double)); + break; + case INT: { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)&(o->type))->value; + // encode v with arithmetic shifts + uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], (v << 1) ^ (v >> 63)); + } + break; + case STRING: + sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); + sBytesPushBuffer(&r, &((sStringt *)&(o->type))->data, sizeof(sStringt) + strlen(&(((sStringt *)&(o->type))->data)) -1); + break; + case ARRAY: + arrayNetSerial(&r, (sArrayt *)&(o->type), &ctx, /*packing=*/NOPACKING); + break; + case BYTES: + B = (sBytest *)&(o->type); + uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], B->count); + sBytesPushBuffer(&r, &(B->data), B->count); + break; + } + ret r; +} + +/** + * serialize dictionary + * + * the serialized dict is pushed to r. + * All elements are serialized recursively + * + * the data in containers is not serialized + * + * \param + * r small bytes object + * dict dictionary to serialize + */ +internal void dictNetSerial(sBytest **r, sDictt *dict, contextt *ctx, packingT packing) { + sBytest *B = NULL; + char *data = NULL; + + // check if all elements have same type + // then set dict type normal or uniform + // array and dict have to be checked recursively to know if they are normal or uniform + bool allElementsHaveSameType = true; + bool foundFirstType = false; + char type = 0; + // get first element type + // compare to other element type + {forEachSDict(dict, e) { + if (e->key) { + if (foundFirstType) { + u8 nextType; + switch(e->data->type) { + case DICT: + nextType = isDictUniform((sDictt*)e->data); + break; + case ARRAY: + nextType = isArrayUniform((sArrayt*)e->data); + break; + default: + nextType = NET_SERIAL_TYPES[(u8)e->data->type]; + } + if (nextType != type) { + allElementsHaveSameType = false; + break; + } + } + else { + switch(e->data->type) { + case DICT: + type = isDictUniform((sDictt*)e->data); + break; + case ARRAY: + type = isArrayUniform((sArrayt*)e->data); + break; + default: + type = NET_SERIAL_TYPES[(u8)e->data->type]; + } + foundFirstType = true; + } + } + }} + + if (allElementsHaveSameType) { + // uniform dict + // encode type and element count + + // in pack dictionary + if (packing == PACKED) { + // uniform dict can't be packed + // because there is only one type of packed arrays + goto normalDict; + } + elif (packing == UNIFORM) { + // when the packing is uniform, there is no need to encode UNIFORM_DICT since all elements have this type + uintToNetTypeVarint(r, type, dict->count); + } + else { + if (ctx->nibble == lowNbl) { + sBytesPush(r, (type << 4) + UNIFORM_DICT); + uintToVarint(r, dict->count); + } + else { + // high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= UNIFORM_DICT << 4; + uintToNetTypeVarint(r, type, dict->count); + } + } + + // encode all element keys and values + switch(type) { + case S_UNDEFINED: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + } + }} + + break; + case S_BOOL: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + + if (!ctx->boolOffset) { + // new packed bools + storeNew8bPackedBool(e->data); + } + else { + // there was a bool before this one, fill bits in nibbles + if (ctx->boolShift == 8) { + // previous packed bool is full + // next byte is the new packed bools + storeNew8bPackedBool(e->data); + } + else { + storeBool(e->data); + } + } + } + }} + break; + case S_DICT: + case UNIFORM_DICT: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + dictNetSerial(r, (sDictt *)(e->data), ctx, /*packing=*/UNIFORM); + } + }} + break; + case S_DOUBLE: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); + } + }} + break; + case S_INT: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + i64 v = ((sIntt *)(e->data))->value; + uintToVarint(r, (v << 1) ^ (v >> 63)); + } + }} + break; + case S_STRING: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); + } + }} + break; + case S_ARRAY: + case UNIFORM_ARRAY: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + arrayNetSerial(r, (sArrayt *)(e->data), ctx, /*packing=*/UNIFORM); + } + }} + break; + case S_BYTES: + {forEachSDict(dict, e) { + if (e->key) { + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + B = (sBytest *)(e->data); + uintToVarint(r, B->count); + sBytesPushBuffer(r, &(B->data), B->count); + } + }} + break; + } + ret; + } + + normalDict: + // encode type and element count + if (packing == PACKED or packing == UNIFORM) { + // when the packing is packed or uniform, there is no need to encode DICT type since all elements have this type + uintToVarint(r, dict->count); + } + else { + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)dict->type], dict->count); + } + else { + // high nibble + #define storeTypeInHighNbl(o)\ + ctx->nibble = lowNbl;\ + data = (char *)&((*r)->data) + ctx->nblOffset;\ + *data |= NET_SERIAL_TYPES[(u8)o->type] << 4 + storeTypeInHighNbl(dict); + uintToVarint(r, dict->count); + } + } + + bool pack = false; + size_t packCount; + enumerateSDict(dict, e, eIdx) { + if (e->key) { + if (!pack) { + // scan dict for packing + if ((dict->count - eIdx) > 3) { + // at least 4 elements, less than that is not worth it + if ( e->data->type == DICT + or e->data->type == DOUBLE + or e->data->type == INT + or e->data->type == STRING + or e->data->type == ARRAY + or e->data->type == BYTES) { + type = e->data->type; + packCount = 1; + sDictElemt *element = &((dict)->elements) + eIdx; + for (size_t i = eIdx+1; i < (dict)->count ; i++, element = &((dict)->elements) + i) { + if (element->key) { + if (element->data->type != type) { + break; + } + packCount++; + } // element->key + } // for + if (packCount > 3) { + type = PACKED_NET_SERIAL_TYPES[(u8)type]; + pack = true; + } + } // test current element type + } // is dict big enough + } // not already packing + + // encode key + sBytesPushBuffer(r, e->key, strlen(e->key) + 1); + + // encode value + switch(e->data->type) { + case UNDEFINED: + case CONTAINER: + if (ctx->nibble == lowNbl) { + #define storeTypeOnly(o)\ + sBytesPush(r, NET_SERIAL_TYPES[(u8)o->type]);\ + ctx->nibble = highNbl;\ + ctx->nblOffset = (*r)->count -1 + storeTypeOnly(e->data); + } + else { + storeTypeInHighNbl(e->data); + } + break; + case BOOL: + if (!ctx->boolOffset) { + // new packed bools + if (ctx->nibble == lowNbl) { + #define storeNew4bPackedBool(o)\ + u8 c = NET_SERIAL_TYPES[(u8)o->type];\ + /* set bit 4 when true */\ + if (((sBoolt *)(o))->value)\ + c |= (1<<4);\ + sBytesPush(r, c);\ + ctx->boolShift = 5;\ + ctx->boolOffset = (*r)->count -1 + storeNew4bPackedBool(e->data); + } + else { + // high nibble, next byte is packed bools + storeTypeInHighNbl(e->data); + #define storeNew8bPackedBool(o)\ + u8 c = 0;\ + if (((sBoolt *)(o))->value)\ + c = 1;\ + sBytesPush(r, c);\ + ctx->boolShift = 1;\ + ctx->boolOffset = (*r)->count -1 + storeNew8bPackedBool(e->data); + } + } + else { + // there was a bool before this one, fill bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + // previous packed bool is full + // this byte is the new packed bools + storeNew4bPackedBool(e->data); + } + else { + storeTypeOnly(e->data); + #define storeBool(o)\ + data = (char *)&((*r)->data) + ctx->boolOffset;\ + if (((sBoolt *)(o))->value)\ + *data |= 1 << ctx->boolShift;\ + ctx->boolShift++ + storeBool(e->data); + } + } + else { + // high nibble + storeTypeInHighNbl(e->data); + if (ctx->boolShift == 8) { + // previous packed bool is full + // next byte is the new packed bools + storeNew8bPackedBool(e->data); + } + else { + storeBool(e->data); + } + } + } + break; + case DICT: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + dictNetSerial(r, (sDictt *)(e->data), ctx, /*packing=*/PACKED); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else + dictNetSerial(r, (sDictt *)(e->data), ctx, /*packing=*/NOPACKING); + break; + case DOUBLE: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else { + if (ctx->nibble == lowNbl) { + storeTypeOnly(e->data); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + } + sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); + } + break; + case INT: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + i64 v = ((sIntt *)(e->data))->value; + uintToVarint(r, (v << 1) ^ (v >> 63)); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)(e->data))->value; + if (ctx->nibble == lowNbl) { + // encode v with arithmetic shifts + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], (v << 1) ^ (v >> 63)); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + uintToVarint(r, (v << 1) ^ (v >> 63)); + } + } + break; + case STRING: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else { + if (ctx->nibble == lowNbl) { + storeTypeOnly(e->data); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + } + sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); + } + break; + case ARRAY: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + arrayNetSerial(r, (sArrayt *)(e->data), ctx, /*packing=*/PACKED); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else + arrayNetSerial(r, (sArrayt *)(e->data), ctx, /*packing=*/NOPACKING); + break; + case BYTES: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + B = (sBytest *)(e->data); + uintToVarint(r, B->count); + sBytesPushBuffer(r, &(B->data), B->count); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else { + B = (sBytest *)(e->data); + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], B->count); + } + else { + // high nibble + storeTypeInHighNbl(e->data); + uintToVarint(r, B->count); + } + sBytesPushBuffer(r, &(B->data), B->count); + } + break; + } + } + } + ret; +} + +/** + * serialize array + * + * the serialized array is pushed to r. + * All elements are serialized recursively + * + * the data in containers is not serialized + * + * \param + * r small bytes object + * array to serialize + */ +internal void arrayNetSerial(sBytest **r, sArrayt *array, contextt *ctx, packingT packing) { + sBytest *B = NULL; + char *data = NULL; + + // check if all elements have same type + // then set array type normal or uniform + // array and dict have to be checked recursively to know if they are normal or uniform + bool allElementsHaveSameType = true; + bool foundFirstType = false; + char type = 0; + + // get first element type + // compare to other element type + // null element are interpreted as undefined + {forEachSArray(array, e) { + if (!e) { + if (foundFirstType) { + if (type != S_UNDEFINED) { + allElementsHaveSameType = false; + break; + } + } + else { + type = S_UNDEFINED; + foundFirstType = true; + } + } + else { + if (foundFirstType) { + u8 nextType; + switch(e->type) { + case DICT: + nextType = isDictUniform((sDictt*)e); + break; + case ARRAY: + nextType = isArrayUniform((sArrayt*)e); + break; + default: + nextType = NET_SERIAL_TYPES[(u8)e->type]; + } + if (nextType != type) { + allElementsHaveSameType = false; + break; + } + } + else { + switch(e->type) { + case DICT: + type = isDictUniform((sDictt*)e); + break; + case ARRAY: + type = isArrayUniform((sArrayt*)e); + break; + default: + type = NET_SERIAL_TYPES[(u8)e->type]; + } + foundFirstType = true; + } + } + }} + + if (allElementsHaveSameType) { + // uniform array + // encode type and element count + + // in pack array + if (packing == PACKED) { + // uniform array can't be packed + // because there is only one type of packed arrays + goto normalArray; + } + elif (packing == UNIFORM) { + // when the packing is uniform, there is no need to encode UNIFORM_ARRAY since all elements have this type + uintToNetTypeVarint(r, type, array->count); + } + else { + if (ctx->nibble == lowNbl) { + sBytesPush(r, (type << 4) + UNIFORM_ARRAY); + uintToVarint(r, array->count); + } + else { + // high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= UNIFORM_ARRAY << 4; + uintToNetTypeVarint(r, type, array->count); + } + } + + // encode all element values + switch(type) { + case S_BOOL: + {forEachSArray(array, e) { + if (!ctx->boolOffset) { + // new packed bools + storeNew8bPackedBool(e); + } + else { + // there was a bool before this one, fill bits in nibbles + if (ctx->boolShift == 8) { + // previous packed bool is full + // next byte is the new packed bools + storeNew8bPackedBool(e); + } + else { + storeBool(e); + } + } + }} + break; + case S_DICT: + case UNIFORM_DICT: + {forEachSArray(array, e) { + dictNetSerial(r, (sDictt *)e, ctx, /*packing=*/UNIFORM); + }} + break; + case S_DOUBLE: + {forEachSArray(array, e) { + sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); + }} + break; + case S_INT: + {forEachSArray(array, e) { + i64 v = ((sIntt *)e)->value; + uintToVarint(r, (v << 1) ^ (v >> 63)); + }} + break; + case S_STRING: + {forEachSArray(array, e) { + sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); + }} + break; + case S_ARRAY: + case UNIFORM_ARRAY: + {forEachSArray(array, e) { + arrayNetSerial(r, (sArrayt *)e, ctx, /*packing=*/UNIFORM); + }} + break; + case S_BYTES: + {forEachSArray(array, e) { + B = (sBytest *)e; + uintToVarint(r, B->count); + sBytesPushBuffer(r, &(B->data), B->count); + }} + break; + } + ret; + } + + normalArray: + // encode type and element count + if (packing == PACKED or packing == UNIFORM) { + // when the packing is packed or uniform, there is no need to encode ARRAY type since all elements have this type + uintToVarint(r, array->count); + } + else { + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)array->type], array->count); + } + else { + // high nibble + storeTypeInHighNbl(array); + uintToVarint(r, array->count); + } + } + + bool pack = false; + size_t packCount; + enumerateSArray(array, e, eIdx) { + if (!e) { + // empty slots are represented as undefined elements + if (ctx->nibble == lowNbl) { + sBytesPush(r, NET_SERIAL_TYPES[UNDEFINED]); + ctx->nibble = highNbl; + ctx->nblOffset = (*r)->count -1; + } + else { + // high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= NET_SERIAL_TYPES[UNDEFINED] << 4; + } + } + else { + if (!pack) { + // scan array for packing + if ((array->count - eIdx) > 3) { + // at least 4 elements, less than that is not worth it + if ( e->type == DICT + or e->type == DOUBLE + or e->type == INT + or e->type == STRING + or e->type == ARRAY + or e->type == BYTES) { + type = e->type; + packCount = 1; + smallt *element = ((smallt **) &((array)->data))[eIdx]; + for (size_t i = eIdx+1; i < (array)->count ; i++, element = ((smallt **) &((array)->data))[i]) { + if (!element) { + // null element are undefined + break; + } + else { + if (element->type != type) { + break; + } + packCount++; + } // if element + } // for + if (packCount > 3) { + type = PACKED_NET_SERIAL_TYPES[(u8)type]; + pack = true; + } + } // test current element type + } // is array big enough + } // not already packing + + // encode element value + switch(e->type) { + case UNDEFINED: + case CONTAINER: + if (ctx->nibble == lowNbl) { + storeTypeOnly(e); + } + else { + // high nibble + storeTypeInHighNbl(e); + } + break; + case BOOL: + if (!ctx->boolOffset) { + // new packed bools + if (ctx->nibble == lowNbl) { + storeNew4bPackedBool(e); + } + else { + // high nibble, next byte is packed bools + storeTypeInHighNbl(e); + storeNew8bPackedBool(e); + } + } + else { + // there was a bool before this one, fill bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + // previous packed bool is full + // this byte is the new packed bools + storeNew4bPackedBool(e); + } + else { + storeTypeOnly(e); + storeBool(e); + } + } + else { + // high nibble + storeTypeInHighNbl(e); + if (ctx->boolShift == 8) { + // previous packed bool is full + // next byte is the new packed bools + storeNew8bPackedBool(e); + } + else { + storeBool(e); + } + } + } + break; + case DICT: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + dictNetSerial(r, (sDictt *)e, ctx, /*packing=*/PACKED); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else + dictNetSerial(r, (sDictt *)e, ctx, /*packing=*/NOPACKING); + break; + case DOUBLE: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else { + if (ctx->nibble == lowNbl) { + storeTypeOnly(e); + } + else { + // high nibble + storeTypeInHighNbl(e); + } + sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); + } + break; + case INT: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + i64 v = ((sIntt *)&(e->type))->value; + uintToVarint(r, (v << 1) ^ (v >> 63)); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else { + // encode int to varint + // v is int64_t to convert to varint + i64 v = ((sIntt *)&(e->type))->value; + if (ctx->nibble == lowNbl) { + // encode v with arithmetic shifts + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], (v << 1) ^ (v >> 63)); + } + else { + // high nibble + storeTypeInHighNbl(e); + uintToVarint(r, (v << 1) ^ (v >> 63)); + } + } + break; + case STRING: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else { + if (ctx->nibble == lowNbl) { + storeTypeOnly(e); + } + else { + // high nibble + storeTypeInHighNbl(e); + } + sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); + } + break; + case ARRAY: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + arrayNetSerial(r, (sArrayt *)e, ctx, /*packing=*/PACKED); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else + arrayNetSerial(r, (sArrayt *)e, ctx, /*packing=*/NOPACKING); + break; + case BYTES: + if (pack) { + if (type) { + // this is the first packed element + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, type, packCount); + } + else { + // high nibble + // store type in high nibble + ctx->nibble = lowNbl; + data = (char *)&((*r)->data) + ctx->nblOffset; + *data |= type << 4; + uintToVarint(r, packCount); + } + type = 0; + } // if type + + B = (sBytest *)e; + uintToVarint(r, B->count); + sBytesPushBuffer(r, &(B->data), B->count); + // stop packing when packCount == 0 + packCount--; + if (!packCount) pack = false; + } // if pack + else { + B = (sBytest *)e; + if (ctx->nibble == lowNbl) { + uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], B->count); + } + else { + // high nibble + storeTypeInHighNbl(e); + uintToVarint(r, B->count); + } + sBytesPushBuffer(r, &(B->data), B->count); + } + break; + } + } + } + ret; +} + +internal smallBytest* serialNetSerial(smallJsont *self) { + + smallt *o = getsoG(self); + + if (o == NULL) + ret NULL; + + sBytest *B = netSerial(o); + + if (!B) { + ret NULL; + } + + createAllocateSmallBytes(r); + r->B = B; + ret r; +} + +// ------------------------------------- +// Deserializers + +// level 0 +// like smallJson with ints and length encoded as varints + +/** + * deserializer top function + */ +internal smallt* netDeserialLevel0(sBytest *obj) { + smallt *r = NULL; + double *D = NULL; + char *s = NULL; + sBytest *B = NULL; + uint32_t count; + char *data = NULL; + + switch(obj->data & 0xF) { + case S_UNDEFINED: + r = (smallt *) allocSUndefined(); + break; + case S_BOOL: + r = (smallt *) allocSBool(obj->data & 0x10); + break; + case S_DICT: + data = (char *)&(obj->data); + dictNetDeserialLevel0((sDictt **)&r, &data); + break; + case S_DOUBLE: + data = &(obj->data)+1; + D = (double *)data; + r = (smallt *) allocSDouble(*D); + break; + case S_INT: + data = &(obj->data); + i64 v = netTypeVarintToUint((u8**)&data); + v = (v >> 1) ^ ((v << 63) >> 63); + r = (smallt *) allocSInt(v); + break; + case S_STRING: + s = (char *)&(obj->data)+1; + r = (smallt *) allocSStringTiny(s); + break; + case S_ARRAY: + data = (char *)&(obj->data); + arrayNetDeserialLevel0((sArrayt **)&r, &data); + break; + case S_BYTES: + B = allocSBytes(); + data = &(obj->data); + count = netTypeVarintToUint((u8**)&data); + sBytesPushBuffer(&B, data, count); + r = (smallt *)B; + break; + } + + ret r; +} + +/** + * deserialize dictionary from data + * + * a new dictionary is allocated + * + * \param + * dict dictionary holding the elements + * data serialized dictionary + */ +internal void dictNetDeserialLevel0(sDictt **dict, char **data) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t dictCount; + + dictCount = netTypeVarintToUint((u8**)data); + + if (!dictCount) { + *dict = allocSDict(); + ret; + } + + loop(dictCount) { + char type; + char *key; + key = *data; + *data += strlen(key)+1; + type = **data; + + switch(type & 0xF) { + case S_UNDEFINED: + (*data)++; + u = allocSUndefined(); + sDictPushTiny(dict, key, (smallt *) u); + break; + case S_BOOL: + (*data)++; + bo = allocSBool(type & 0x10); + sDictPushTiny(dict, key, (smallt *) bo); + break; + case S_DICT: + d = NULL; + dictNetDeserialLevel0(&d, data); + sDictPushTiny(dict, key, (smallt *) d); + break; + case S_DOUBLE: + (*data)++; + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sDictPushTiny(dict, key, (smallt *) Do); + break; + case S_INT: { + i64 v = netTypeVarintToUint((u8**)data); + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sDictPushTiny(dict, key, (smallt *) io); + } + break; + case S_STRING: + (*data)++; + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sDictPushTiny(dict, key, (smallt *) so); + break; + case S_ARRAY: + a = NULL; + arrayNetDeserialLevel0(&a, data); + sDictPushTiny(dict, key, (smallt *) a); + break; + case S_BYTES: + B = allocSBytes(); + count = netTypeVarintToUint((u8**)data); + sBytesPushBuffer(&B, data, count); + *data += count; + sDictPushTiny(dict, key, (smallt *) B); + break; + } + } +} + +/** + * deserialize array from data + * + * a new array is allocated + * + * \param + * array holding the elements + * data serialized dictionary + */ +internal void arrayNetDeserialLevel0(sArrayt **array, char **data) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t arrayCount; + + arrayCount = netTypeVarintToUint((u8**)data); + + if (!arrayCount) { + *array = allocSArray();; + ret; + } + + loop(arrayCount) { + char type; + type = **data; + + switch(type & 0xF) { + case S_UNDEFINED: + (*data)++; + u = allocSUndefined(); + sArrayPushTiny(array, (smallt *) u); + break; + case S_BOOL: + (*data)++; + bo = allocSBool(type & 0x10); + sArrayPushTiny(array, (smallt *) bo); + break; + case S_DICT: + d = NULL; + dictNetDeserialLevel0(&d, data); + sArrayPushTiny(array, (smallt *) d); + break; + case S_DOUBLE: + (*data)++; + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sArrayPushTiny(array, (smallt *) Do); + break; + case S_INT: { + i64 v = netTypeVarintToUint((u8**)data); + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sArrayPushTiny(array, (smallt *) io); + } + break; + case S_STRING: + (*data)++; + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sArrayPushTiny(array, (smallt *) so); + break; + case S_ARRAY: + a = NULL; + arrayNetDeserialLevel0(&a, data); + sArrayPushTiny(array, (smallt *) a); + break; + case S_BYTES: + B = allocSBytes(); + count = netTypeVarintToUint((u8**)data); + sBytesPushBuffer(&B, data, count); + *data += count; + sArrayPushTiny(array, (smallt *) B); + break; + } + } +} + +internal smallJsont* deserialNetSerialLevel0(smallJsont *self, smallBytest *data) { + + if (!data) { + ret self; + } + + smallt *o = netDeserialLevel0(data->B); + + if (!o) { + ret self; + } + + freeG(self); + + setsoG(self, o); + + ret self; +} + +// level 1 +// like level 0 with type encoded in nibbles and bools are packed + +/** + * deserializer top function + */ +internal smallt* netDeserialLevel1(sBytest *obj) { + smallt *r = NULL; + double *D = NULL; + char *s = NULL; + sBytest *B = NULL; + uint32_t count; + char *data = NULL; + contextt ctx = {.nibble=lowNbl, .nblAddr=NULL, .boolShift = 0, .boolAddr=NULL}; + + switch(obj->data & 0xF) { + case S_UNDEFINED: + r = (smallt *) allocSUndefined(); + break; + case S_BOOL: + r = (smallt *) allocSBool(obj->data & 0x10); + break; + case S_DICT: + data = (char *)&(obj->data); + //debug - ctx.dbuf = (u8*) data; + dictNetDeserialLevel1((sDictt **)&r, (u8**)&data, &ctx); + break; + case S_DOUBLE: + data = &(obj->data)+1; + D = (double *)data; + r = (smallt *) allocSDouble(*D); + break; + case S_INT: + data = &(obj->data); + i64 v = netTypeVarintToUint((u8**)&data); + v = (v >> 1) ^ ((v << 63) >> 63); + r = (smallt *) allocSInt(v); + break; + case S_STRING: + s = (char *)&(obj->data)+1; + r = (smallt *) allocSStringTiny(s); + break; + case S_ARRAY: + data = (char *)&(obj->data); + //debug - ctx.dbuf = (u8*) data; + arrayNetDeserialLevel1((sArrayt **)&r, (u8**)&data, &ctx); + break; + case S_BYTES: + B = allocSBytes(); + data = &(obj->data); + count = netTypeVarintToUint((u8**)&data); + sBytesPushBuffer(&B, data, count); + r = (smallt *)B; + break; + } + + ret r; +} + +/** + * deserialize dictionary from data + * + * a new dictionary is allocated + * + * \param + * dict dictionary holding the elements + * data serialized dictionary + */ +internal void dictNetDeserialLevel1(sDictt **dict, u8 **data, contextt *ctx) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t dictCount; + + if (ctx->nibble == lowNbl) { + dictCount = netTypeVarintToUint(data); + } + else { + // high nibble + // type = *(ctx->dbuf + ctx->nblOffset) >> 4; + #define readTypeInHighNbl\ + ctx->nibble = lowNbl;\ + if (ctx->nblAddr == *data)\ + /* data points to the type, next byte is count */\ + (*data)++ + readTypeInHighNbl; + dictCount = varintToUint(data); + } + + if (!dictCount) { + *dict = allocSDict(); + ret; + } + + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + char type; + if (ctx->nibble == lowNbl) { + type = (**data) & 0xF; + } + else { + // high nibble + type = (*ctx->nblAddr) >> 4; + } + + switch(type) { + case S_UNDEFINED: + if (ctx->nibble == lowNbl) { + #define readTypeOnly\ + ctx->nibble = highNbl;\ + ctx->nblAddr = *data;\ + (*data)++ + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + u = allocSUndefined(); + sDictPushTiny(dict, key, (smallt *) u); + break; + case S_BOOL: + if (!ctx->boolAddr) { + // new packed bools + if (ctx->nibble == lowNbl) { + #define read4bPackedBool\ + ctx->boolShift = 5;\ + ctx->boolAddr = *data;\ + (*data)++ + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + // high nibble + readTypeInHighNbl; + #define read8bPackedBool\ + ctx->boolShift = 1;\ + ctx->boolAddr = *data;\ + (*data)++ + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + } + else { + // there was a bool before this one, read bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + readTypeOnly; + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + else { + // high nibble + readTypeInHighNbl; + if (ctx->boolShift == 8) { + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + else { + // high nibble + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + } + sDictPushTiny(dict, key, (smallt *) bo); + break; + case S_DICT: + d = NULL; + dictNetDeserialLevel1(&d, data, ctx); + sDictPushTiny(dict, key, (smallt *) d); + break; + case S_DOUBLE: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sDictPushTiny(dict, key, (smallt *) Do); + break; + case S_INT: { + i64 v; + if (ctx->nibble == lowNbl) { + v = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + v = varintToUint(data); + } + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sDictPushTiny(dict, key, (smallt *) io); + } + break; + case S_STRING: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sDictPushTiny(dict, key, (smallt *) so); + break; + case S_ARRAY: + a = NULL; + arrayNetDeserialLevel1(&a, data, ctx); + sDictPushTiny(dict, key, (smallt *) a); + break; + case S_BYTES: + B = allocSBytes(); + if (ctx->nibble == lowNbl) { + count = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + count = varintToUint((u8**)data); + } + sBytesPushBuffer(&B, data, count); + *data += count; + sDictPushTiny(dict, key, (smallt *) B); + break; + } + } +} + +/** + * deserialize array from data + * + * a new array is allocated + * + * \param + * array holding the elements + * data serialized dictionary + */ +internal void arrayNetDeserialLevel1(sArrayt **array, u8 **data, contextt *ctx) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t arrayCount; + + if (ctx->nibble == lowNbl) { + arrayCount = netTypeVarintToUint(data); + } + else { + // high nibble + readTypeInHighNbl; + arrayCount = varintToUint(data); + } + + if (!arrayCount) { + *array = allocSArray();; + ret; + } + + loop(arrayCount) { + char type; + if (ctx->nibble == lowNbl) { + type = (**data) & 0xF; + } + else { + // high nibble + type = (*ctx->nblAddr) >> 4; + } + + switch(type) { + case S_UNDEFINED: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + u = allocSUndefined(); + sArrayPushTiny(array, (smallt *) u); + break; + case S_BOOL: + if (!ctx->boolAddr) { + // new packed bools + if (ctx->nibble == lowNbl) { + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + // high nibble + readTypeInHighNbl; + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + } + else { + // there was a bool before this one, read bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + readTypeOnly; + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + else { + // high nibble + readTypeInHighNbl; + if (ctx->boolShift == 8) { + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + else { + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + } + sArrayPushTiny(array, (smallt *) bo); + break; + case S_DICT: + d = NULL; + dictNetDeserialLevel1(&d, data, ctx); + sArrayPushTiny(array, (smallt *) d); + break; + case S_DOUBLE: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sArrayPushTiny(array, (smallt *) Do); + break; + case S_INT: { + i64 v; + if (ctx->nibble == lowNbl) { + v = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + v = varintToUint(data); + } + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sArrayPushTiny(array, (smallt *) io); + } + break; + case S_STRING: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sArrayPushTiny(array, (smallt *) so); + break; + case S_ARRAY: + a = NULL; + arrayNetDeserialLevel1(&a, data, ctx); + sArrayPushTiny(array, (smallt *) a); + break; + case S_BYTES: + B = allocSBytes(); + if (ctx->nibble == lowNbl) { + count = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + count = varintToUint((u8**)data); + } + sBytesPushBuffer(&B, data, count); + *data += count; + sArrayPushTiny(array, (smallt *) B); + break; + } + } +} + +internal smallJsont* deserialNetSerialLevel1(smallJsont *self, smallBytest *data) { + + if (!data) { + ret self; + } + + smallt *o = netDeserialLevel1(data->B); + + if (!o) { + ret self; + } + + freeG(self); + + setsoG(self, o); + + ret self; +} + +// level 2 +// like level 1, arrays are set to uniform when all elements are same type + +/** + * deserializer top function + */ +internal smallt* netDeserialLevel2(sBytest *obj) { + smallt *r = NULL; + double *D = NULL; + char *s = NULL; + sBytest *B = NULL; + uint32_t count; + char *data = NULL; + contextt ctx = {.nibble=lowNbl, .nblAddr=NULL, .boolShift = 0, .boolAddr=NULL}; + + switch(obj->data & 0xF) { + case S_UNDEFINED: + r = (smallt *) allocSUndefined(); + break; + case S_BOOL: + r = (smallt *) allocSBool(obj->data & 0x10); + break; + case S_DICT: + data = (char *)&(obj->data); + //debug - ctx.dbuf = (u8*) data; + dictNetDeserialLevel2((sDictt **)&r, (u8**)&data, &ctx, /*packed=*/false); + break; + case S_DOUBLE: + data = &(obj->data)+1; + D = (double *)data; + r = (smallt *) allocSDouble(*D); + break; + case S_INT: + data = &(obj->data); + i64 v = netTypeVarintToUint((u8**)&data); + v = (v >> 1) ^ ((v << 63) >> 63); + r = (smallt *) allocSInt(v); + break; + case S_STRING: + s = (char *)&(obj->data)+1; + r = (smallt *) allocSStringTiny(s); + break; + case S_ARRAY: + data = (char *)&(obj->data); + //debug - ctx.dbuf = (u8*) data; + arrayNetDeserialLevel2((sArrayt **)&r, (u8**)&data, &ctx, /*packed=*/false); + break; + case S_BYTES: + B = allocSBytes(); + data = &(obj->data); + count = netTypeVarintToUint((u8**)&data); + sBytesPushBuffer(&B, data, count); + r = (smallt *)B; + break; + case UNIFORM_DICT: + data = (char *)&(obj->data); + //debug - ctx.dbuf = (u8*) data; + uniformDictNetDeserialLevel2((sDictt **)&r, (u8**)&data, &ctx, /*packed=*/false); + break; + case UNIFORM_ARRAY: + data = (char *)&(obj->data); + //debug - ctx.dbuf = (u8*) data; + uniformArrayNetDeserialLevel2((sArrayt **)&r, (u8**)&data, &ctx, /*packed=*/false); + break; + } + + ret r; +} + +/** + * deserialize dictionary from data + * + * a new dictionary is allocated + * + * \param + * dict dictionary holding the elements + * data serialized dictionary + */ +internal void dictNetDeserialLevel2(sDictt **dict, u8 **data, contextt *ctx, bool packed) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t dictCount; + + if (packed) { + dictCount = varintToUint(data); + } + else { + if (ctx->nibble == lowNbl) { + dictCount = netTypeVarintToUint(data); + } + else { + // high nibble + // type = *(ctx->dbuf + ctx->nblOffset) >> 4; + #define readTypeInHighNbl\ + ctx->nibble = lowNbl;\ + if (ctx->nblAddr == *data)\ + /* data points to the type, next byte is count */\ + (*data)++ + readTypeInHighNbl; + dictCount = varintToUint(data); + } + } + + if (!dictCount) { + *dict = allocSDict(); + ret; + } + + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + char type; + if (ctx->nibble == lowNbl) { + type = (**data) & 0xF; + } + else { + // high nibble + type = (*ctx->nblAddr) >> 4; + } + + switch(type) { + case S_UNDEFINED: + if (ctx->nibble == lowNbl) { + #define readTypeOnly\ + ctx->nibble = highNbl;\ + ctx->nblAddr = *data;\ + (*data)++ + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + u = allocSUndefined(); + sDictPushTiny(dict, key, (smallt *) u); + break; + case S_BOOL: + if (!ctx->boolAddr) { + // new packed bools + if (ctx->nibble == lowNbl) { + #define read4bPackedBool\ + ctx->boolShift = 5;\ + ctx->boolAddr = *data;\ + (*data)++ + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + // high nibble + readTypeInHighNbl; + #define read8bPackedBool\ + ctx->boolShift = 1;\ + ctx->boolAddr = *data;\ + (*data)++ + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + } + else { + // there was a bool before this one, read bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + readTypeOnly; + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + else { + // high nibble + readTypeInHighNbl; + if (ctx->boolShift == 8) { + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + else { + // high nibble + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + } + sDictPushTiny(dict, key, (smallt *) bo); + break; + case S_DICT: + d = NULL; + dictNetDeserialLevel2(&d, data, ctx, /*packed=*/false); + sDictPushTiny(dict, key, (smallt *) d); + break; + case S_DOUBLE: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sDictPushTiny(dict, key, (smallt *) Do); + break; + case S_INT: { + i64 v; + if (ctx->nibble == lowNbl) { + v = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + v = varintToUint(data); + } + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sDictPushTiny(dict, key, (smallt *) io); + } + break; + case S_STRING: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sDictPushTiny(dict, key, (smallt *) so); + break; + case S_ARRAY: + a = NULL; + arrayNetDeserialLevel2(&a, data, ctx, /*packed=*/false); + sDictPushTiny(dict, key, (smallt *) a); + break; + case S_BYTES: + B = allocSBytes(); + if (ctx->nibble == lowNbl) { + count = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + count = varintToUint((u8**)data); + } + sBytesPushBuffer(&B, data, count); + *data += count; + sDictPushTiny(dict, key, (smallt *) B); + break; + case UNIFORM_DICT: + d = NULL; + uniformDictNetDeserialLevel2(&d, data, ctx, /*packed=*/false); + sDictPushTiny(dict, key, (smallt *) d); + break; + case UNIFORM_ARRAY: + a = NULL; + uniformArrayNetDeserialLevel2(&a, data, ctx, /*packed=*/false); + sDictPushTiny(dict, key, (smallt *) a); + break; + } + } +} + +/** + * deserialize dictionary from data + * + * a new dictionary is allocated + * + * \param + * dict dictionary holding the elements + * data serialized dictionary + */ +internal void uniformDictNetDeserialLevel2(sDictt **dict, u8 **data, contextt *ctx, bool packed) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t dictCount; + u8 type; + + if (packed) { + type = (**data) & 0xF; + dictCount = netTypeVarintToUint(data); + } + else { + if (ctx->nibble == lowNbl) { + type = (**data) >> 4; + (*data)++; + dictCount = varintToUint(data); + } + else { + readTypeInHighNbl; + type = (**data) & 0xF; + dictCount = netTypeVarintToUint(data); + } + } + + if (!dictCount) { + *dict = allocSDict(); + ret; + } + + + switch(type) { + case S_UNDEFINED: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + u = allocSUndefined(); + sDictPushTiny(dict, key, (smallt *) u); + } + break; + case S_BOOL: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + if (!ctx->boolAddr) { + read8bPackedBool; + ctx->boolShift = 0; + } + if (ctx->boolShift == 8) { + readTypeInHighNbl; + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + else { + // high nibble + readTypeInHighNbl; + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + sDictPushTiny(dict, key, (smallt *) bo); + } + break; + case S_DICT: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + d = NULL; + dictNetDeserialLevel2(&d, data, ctx, /*packed=*/true); + sDictPushTiny(dict, key, (smallt *) d); + } + break; + case S_DOUBLE: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sDictPushTiny(dict, key, (smallt *) Do); + } + break; + case S_INT: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + i64 v = varintToUint(data); + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sDictPushTiny(dict, key, (smallt *) io); + } + break; + case S_STRING: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sDictPushTiny(dict, key, (smallt *) so); + } + break; + case S_ARRAY: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + a = NULL; + arrayNetDeserialLevel2(&a, data, ctx, /*packed=*/true); + sDictPushTiny(dict, key, (smallt *) a); + } + break; + case S_BYTES: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + B = allocSBytes(); + count = varintToUint((u8**)data); + sBytesPushBuffer(&B, data, count); + *data += count; + sDictPushTiny(dict, key, (smallt *) B); + } + break; + case UNIFORM_DICT: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + d = NULL; + uniformDictNetDeserialLevel2(&d, data, ctx, /*packed=*/true); + sDictPushTiny(dict, key, (smallt *) d); + } + break; + case UNIFORM_ARRAY: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + a = NULL; + uniformArrayNetDeserialLevel2(&a, data, ctx, /*packed=*/true); + sDictPushTiny(dict, key, (smallt *) a); + } + break; + } +} + +/** + * deserialize array from data + * + * a new array is allocated + * + * \param + * array holding the elements + * data serialized dictionary + */ +internal void arrayNetDeserialLevel2(sArrayt **array, u8 **data, contextt *ctx, bool packed) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t arrayCount; + + if (packed) { + arrayCount = varintToUint(data); + } + else { + if (ctx->nibble == lowNbl) { + arrayCount = netTypeVarintToUint(data); + } + else { + // high nibble + readTypeInHighNbl; + arrayCount = varintToUint(data); + } + } + + if (!arrayCount) { + *array = allocSArray();; + ret; + } + + loop(arrayCount) { + char type; + if (ctx->nibble == lowNbl) { + type = (**data) & 0xF; + } + else { + // high nibble + type = (*ctx->nblAddr) >> 4; + } + + switch(type) { + case S_UNDEFINED: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + u = allocSUndefined(); + sArrayPushTiny(array, (smallt *) u); + break; + case S_BOOL: + if (!ctx->boolAddr) { + // new packed bools + if (ctx->nibble == lowNbl) { + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + // high nibble + readTypeInHighNbl; + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + } + else { + // there was a bool before this one, read bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + readTypeOnly; + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + else { + // high nibble + readTypeInHighNbl; + if (ctx->boolShift == 8) { + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + else { + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + } + sArrayPushTiny(array, (smallt *) bo); + break; + case S_DICT: + d = NULL; + dictNetDeserialLevel2(&d, data, ctx, /*packed=*/false); + sArrayPushTiny(array, (smallt *) d); + break; + case S_DOUBLE: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sArrayPushTiny(array, (smallt *) Do); + break; + case S_INT: { + i64 v; + if (ctx->nibble == lowNbl) { + v = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + v = varintToUint(data); + } + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sArrayPushTiny(array, (smallt *) io); + } + break; + case S_STRING: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sArrayPushTiny(array, (smallt *) so); + break; + case S_ARRAY: + a = NULL; + arrayNetDeserialLevel2(&a, data, ctx, /*packed=*/false); + sArrayPushTiny(array, (smallt *) a); + break; + case S_BYTES: + B = allocSBytes(); + if (ctx->nibble == lowNbl) { + count = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + count = varintToUint((u8**)data); + } + sBytesPushBuffer(&B, data, count); + *data += count; + sArrayPushTiny(array, (smallt *) B); + break; + case UNIFORM_DICT: + d = NULL; + uniformDictNetDeserialLevel2(&d, data, ctx, /*packed=*/false); + sArrayPushTiny(array, (smallt *) d); + break; + case UNIFORM_ARRAY: + a = NULL; + uniformArrayNetDeserialLevel2(&a, data, ctx, /*packed=*/false); + sArrayPushTiny(array, (smallt *) a); + break; + } + } +} + +internal void uniformArrayNetDeserialLevel2(sArrayt **array, u8 **data, contextt *ctx, bool packed) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t arrayCount; + u8 type; + + if (packed) { + type = (**data) & 0xF; + arrayCount = netTypeVarintToUint(data); + } + else { + if (ctx->nibble == lowNbl) { + type = (**data) >> 4; + (*data)++; + arrayCount = varintToUint(data); + } + else { + readTypeInHighNbl; + type = (**data) & 0xF; + arrayCount = netTypeVarintToUint(data); + } + } + + if (!arrayCount) { + *array = allocSArray();; + ret; + } + + switch(type) { + case S_UNDEFINED: + loop(arrayCount) { + u = allocSUndefined(); + sArrayPushTiny(array, (smallt *) u); + } + break; + case S_BOOL: + loop(arrayCount) { + if (!ctx->boolAddr) { + read8bPackedBool; + ctx->boolShift = 0; + } + if (ctx->boolShift == 8) { + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + else { + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + sArrayPushTiny(array, (smallt *) bo); + } + break; + case S_DICT: + loop(arrayCount) { + d = NULL; + dictNetDeserialLevel2(&d, data, ctx, /*packed=*/true); + sArrayPushTiny(array, (smallt *) d); + } + break; + case S_DOUBLE: + loop(arrayCount) { + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sArrayPushTiny(array, (smallt *) Do); + } + break; + case S_INT: + loop(arrayCount) { + i64 v = varintToUint(data); + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sArrayPushTiny(array, (smallt *) io); + } + break; + case S_STRING: + loop(arrayCount) { + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sArrayPushTiny(array, (smallt *) so); + } + break; + case S_ARRAY: + loop(arrayCount) { + a = NULL; + arrayNetDeserialLevel2(&a, data, ctx, /*packed=*/true); + sArrayPushTiny(array, (smallt *) a); + } + break; + case S_BYTES: + loop(arrayCount) { + B = allocSBytes(); + count = varintToUint((u8**)data); + sBytesPushBuffer(&B, data, count); + *data += count; + sArrayPushTiny(array, (smallt *) B); + } + break; + case UNIFORM_DICT: + loop(arrayCount) { + d = NULL; + uniformDictNetDeserialLevel2(&d, data, ctx, /*packed=*/true); + sArrayPushTiny(array, (smallt *) d); + } + break; + case UNIFORM_ARRAY: + loop(arrayCount) { + a = NULL; + uniformArrayNetDeserialLevel2(&a, data, ctx, /*packed=*/true); + sArrayPushTiny(array, (smallt *) a); + } + break; + } +} + +internal smallJsont* deserialNetSerialLevel2(smallJsont *self, smallBytest *data) { + + if (!data) { + ret self; + } + + smallt *o = netDeserialLevel2(data->B); + + if (!o) { + ret self; + } + + freeG(self); + + setsoG(self, o); + + ret self; +} + +// level 3 +// like level 2, elements of identical type in a row are packed + +/** + * deserializer top function + */ +internal smallt* netDeserial(sBytest *obj) { + smallt *r = NULL; + double *D = NULL; + char *s = NULL; + sBytest *B = NULL; + uint32_t count; + char *data = NULL; + contextt ctx = {.nibble=lowNbl, .nblAddr=NULL, .boolShift = 0, .boolAddr=NULL}; + + switch(obj->data & 0xF) { + case S_UNDEFINED: + r = (smallt *) allocSUndefined(); + break; + case S_BOOL: + r = (smallt *) allocSBool(obj->data & 0x10); + break; + case S_DICT: + data = (char *)&(obj->data); + //debug - ctx.dbuf = (u8*) data; + dictNetDeserial((sDictt **)&r, (u8**)&data, &ctx, /*packed=*/false); + break; + case S_DOUBLE: + data = &(obj->data)+1; + D = (double *)data; + r = (smallt *) allocSDouble(*D); + break; + case S_INT: + data = &(obj->data); + i64 v = netTypeVarintToUint((u8**)&data); + v = (v >> 1) ^ ((v << 63) >> 63); + r = (smallt *) allocSInt(v); + break; + case S_STRING: + s = (char *)&(obj->data)+1; + r = (smallt *) allocSStringTiny(s); + break; + case S_ARRAY: + data = (char *)&(obj->data); + //debug - ctx.dbuf = (u8*) data; + arrayNetDeserial((sArrayt **)&r, (u8**)&data, &ctx, /*packed=*/false); + break; + case S_BYTES: + B = allocSBytes(); + data = &(obj->data); + count = netTypeVarintToUint((u8**)&data); + sBytesPushBuffer(&B, data, count); + r = (smallt *)B; + break; + case UNIFORM_DICT: + data = (char *)&(obj->data); + //debug - ctx.dbuf = (u8*) data; + uniformDictNetDeserial((sDictt **)&r, (u8**)&data, &ctx, /*packed=*/false); + break; + case UNIFORM_ARRAY: + data = (char *)&(obj->data); + //debug - ctx.dbuf = (u8*) data; + uniformArrayNetDeserial((sArrayt **)&r, (u8**)&data, &ctx, /*packed=*/false); + break; + } + + ret r; +} + +/** + * deserialize dictionary from data + * + * a new dictionary is allocated + * + * \param + * dict dictionary holding the elements + * data serialized dictionary + */ +internal void dictNetDeserial(sDictt **dict, u8 **data, contextt *ctx, bool packed) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t dictCount; + + if (packed) { + dictCount = varintToUint(data); + } + else { + if (ctx->nibble == lowNbl) { + dictCount = netTypeVarintToUint(data); + } + else { + // high nibble + // type = *(ctx->dbuf + ctx->nblOffset) >> 4; + #define readTypeInHighNbl\ + ctx->nibble = lowNbl;\ + if (ctx->nblAddr == *data)\ + /* data points to the type, next byte is count */\ + (*data)++ + readTypeInHighNbl; + dictCount = varintToUint(data); + } + } + + if (!dictCount) { + *dict = allocSDict(); + ret; + } + + bool inPack = false; + u8 packedType; + size_t packCount; + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + char type; + if (inPack) { + type = packedType; + } + else { + if (ctx->nibble == lowNbl) { + type = (**data) & 0xF; + } + else { + // high nibble + type = (*ctx->nblAddr) >> 4; + } + } + + switch(type) { + case S_UNDEFINED: + if (ctx->nibble == lowNbl) { + #define readTypeOnly\ + ctx->nibble = highNbl;\ + ctx->nblAddr = *data;\ + (*data)++ + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + u = allocSUndefined(); + sDictPushTiny(dict, key, (smallt *) u); + break; + case S_BOOL: + if (!ctx->boolAddr) { + // new packed bools + if (ctx->nibble == lowNbl) { + #define read4bPackedBool\ + ctx->boolShift = 5;\ + ctx->boolAddr = *data;\ + (*data)++ + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + // high nibble + readTypeInHighNbl; + #define read8bPackedBool\ + ctx->boolShift = 1;\ + ctx->boolAddr = *data;\ + (*data)++ + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + } + else { + // there was a bool before this one, read bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + readTypeOnly; + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + else { + // high nibble + readTypeInHighNbl; + if (ctx->boolShift == 8) { + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + else { + // high nibble + readTypeInHighNbl; + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + } + sDictPushTiny(dict, key, (smallt *) bo); + break; + case S_DICT: + d = NULL; + dictNetDeserial(&d, data, ctx, /*packed=*/false); + sDictPushTiny(dict, key, (smallt *) d); + break; + case S_DOUBLE: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sDictPushTiny(dict, key, (smallt *) Do); + break; + case S_INT: { + i64 v; + if (ctx->nibble == lowNbl) { + v = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + v = varintToUint(data); + } + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sDictPushTiny(dict, key, (smallt *) io); + } + break; + case S_STRING: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sDictPushTiny(dict, key, (smallt *) so); + break; + case S_ARRAY: + a = NULL; + arrayNetDeserial(&a, data, ctx, /*packed=*/false); + sDictPushTiny(dict, key, (smallt *) a); + break; + case S_BYTES: + B = allocSBytes(); + if (ctx->nibble == lowNbl) { + count = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + count = varintToUint((u8**)data); + } + sBytesPushBuffer(&B, data, count); + *data += count; + sDictPushTiny(dict, key, (smallt *) B); + break; + case PK_DICT: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_DICT; + } + + d = NULL; + dictNetDeserial(&d, data, ctx, /*packed=*/true); + sDictPushTiny(dict, key, (smallt *) d); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case PK_DOUBLE: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_DOUBLE; + } + + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sDictPushTiny(dict, key, (smallt *) Do); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case PK_INT: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_INT; + } + + i64 v = varintToUint(data); + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sDictPushTiny(dict, key, (smallt *) io); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case PK_STRING: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_STRING; + } + + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sDictPushTiny(dict, key, (smallt *) so); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case PK_ARRAY: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_ARRAY; + } + + a = NULL; + arrayNetDeserial(&a, data, ctx, /*packed=*/true); + sDictPushTiny(dict, key, (smallt *) a); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case PK_BYTES: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_BYTES; + } + + B = allocSBytes(); + count = varintToUint((u8**)data); + sBytesPushBuffer(&B, data, count); + *data += count; + sDictPushTiny(dict, key, (smallt *) B); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case UNIFORM_DICT: + d = NULL; + uniformDictNetDeserial(&d, data, ctx, /*packed=*/false); + sDictPushTiny(dict, key, (smallt *) d); + break; + case UNIFORM_ARRAY: + a = NULL; + uniformArrayNetDeserial(&a, data, ctx, /*packed=*/false); + sDictPushTiny(dict, key, (smallt *) a); + break; + } + } +} + +/** + * deserialize dictionary from data + * + * a new dictionary is allocated + * + * \param + * dict dictionary holding the elements + * data serialized dictionary + */ +internal void uniformDictNetDeserial(sDictt **dict, u8 **data, contextt *ctx, bool packed) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t dictCount; + u8 type; + + if (packed) { + type = (**data) & 0xF; + dictCount = netTypeVarintToUint(data); + } + else { + if (ctx->nibble == lowNbl) { + type = (**data) >> 4; + (*data)++; + dictCount = varintToUint(data); + } + else { + readTypeInHighNbl; + type = (**data) & 0xF; + dictCount = netTypeVarintToUint(data); + } + } + + if (!dictCount) { + *dict = allocSDict(); + ret; + } + + + switch(type) { + case S_UNDEFINED: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + u = allocSUndefined(); + sDictPushTiny(dict, key, (smallt *) u); + } + break; + case S_BOOL: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + if (!ctx->boolAddr) { + read8bPackedBool; + ctx->boolShift = 0; + } + if (ctx->boolShift == 8) { + readTypeInHighNbl; + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + else { + // high nibble + readTypeInHighNbl; + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + sDictPushTiny(dict, key, (smallt *) bo); + } + break; + case S_DICT: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + d = NULL; + dictNetDeserial(&d, data, ctx, /*packed=*/true); + sDictPushTiny(dict, key, (smallt *) d); + } + break; + case S_DOUBLE: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sDictPushTiny(dict, key, (smallt *) Do); + } + break; + case S_INT: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + i64 v = varintToUint(data); + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sDictPushTiny(dict, key, (smallt *) io); + } + break; + case S_STRING: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sDictPushTiny(dict, key, (smallt *) so); + } + break; + case S_ARRAY: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + a = NULL; + arrayNetDeserial(&a, data, ctx, /*packed=*/true); + sDictPushTiny(dict, key, (smallt *) a); + } + break; + case S_BYTES: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + B = allocSBytes(); + count = varintToUint((u8**)data); + sBytesPushBuffer(&B, data, count); + *data += count; + sDictPushTiny(dict, key, (smallt *) B); + } + break; + case UNIFORM_DICT: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + d = NULL; + uniformDictNetDeserial(&d, data, ctx, /*packed=*/true); + sDictPushTiny(dict, key, (smallt *) d); + } + break; + case UNIFORM_ARRAY: + loop(dictCount) { + char *key = (char*)*data; + *data += strlen(key)+1; + a = NULL; + uniformArrayNetDeserial(&a, data, ctx, /*packed=*/true); + sDictPushTiny(dict, key, (smallt *) a); + } + break; + } +} + +/** + * deserialize array from data + * + * a new array is allocated + * + * \param + * array holding the elements + * data serialized dictionary + */ +internal void arrayNetDeserial(sArrayt **array, u8 **data, contextt *ctx, bool packed) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t arrayCount; + + if (packed) { + arrayCount = varintToUint(data); + } + else { + if (ctx->nibble == lowNbl) { + arrayCount = netTypeVarintToUint(data); + } + else { + // high nibble + readTypeInHighNbl; + arrayCount = varintToUint(data); + } + } + + if (!arrayCount) { + *array = allocSArray();; + ret; + } + + bool inPack = false; + u8 packedType; + size_t packCount; + loop(arrayCount) { + char type; + if (inPack) { + type = packedType; + } + else { + if (ctx->nibble == lowNbl) { + type = (**data) & 0xF; + } + else { + // high nibble + type = (*ctx->nblAddr) >> 4; + } + } + + switch(type) { + case S_UNDEFINED: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + u = allocSUndefined(); + sArrayPushTiny(array, (smallt *) u); + break; + case S_BOOL: + if (!ctx->boolAddr) { + // new packed bools + if (ctx->nibble == lowNbl) { + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + // high nibble + readTypeInHighNbl; + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + } + else { + // there was a bool before this one, read bits in nibbles + if (ctx->nibble == lowNbl) { + if (ctx->boolShift == 8) { + read4bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x10); + } + else { + readTypeOnly; + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + else { + // high nibble + readTypeInHighNbl; + if (ctx->boolShift == 8) { + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + else { + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + } + } + sArrayPushTiny(array, (smallt *) bo); + break; + case S_DICT: + d = NULL; + dictNetDeserial(&d, data, ctx, /*packed=*/false); + sArrayPushTiny(array, (smallt *) d); + break; + case S_DOUBLE: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sArrayPushTiny(array, (smallt *) Do); + break; + case S_INT: { + i64 v; + if (ctx->nibble == lowNbl) { + v = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + v = varintToUint(data); + } + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sArrayPushTiny(array, (smallt *) io); + } + break; + case S_STRING: + if (ctx->nibble == lowNbl) { + readTypeOnly; + } + else { + // high nibble + readTypeInHighNbl; + } + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sArrayPushTiny(array, (smallt *) so); + break; + case S_ARRAY: + a = NULL; + arrayNetDeserial(&a, data, ctx, /*packed=*/false); + sArrayPushTiny(array, (smallt *) a); + break; + case S_BYTES: + B = allocSBytes(); + if (ctx->nibble == lowNbl) { + count = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + count = varintToUint((u8**)data); + } + sBytesPushBuffer(&B, data, count); + *data += count; + sArrayPushTiny(array, (smallt *) B); + break; + case PK_DICT: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_DICT; + } + + d = NULL; + dictNetDeserial(&d, data, ctx, /*packed=*/true); + sArrayPushTiny(array, (smallt *) d); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case PK_DOUBLE: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_DOUBLE; + } + + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sArrayPushTiny(array, (smallt *) Do); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case PK_INT: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_INT; + } + + i64 v = varintToUint(data); + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sArrayPushTiny(array, (smallt *) io); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case PK_STRING: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_STRING; + } + + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sArrayPushTiny(array, (smallt *) so); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case PK_ARRAY: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_ARRAY; + } + + a = NULL; + arrayNetDeserial(&a, data, ctx, /*packed=*/true); + sArrayPushTiny(array, (smallt *) a); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case PK_BYTES: + if (!inPack) { + inPack = true; + if (ctx->nibble == lowNbl) { + packCount = netTypeVarintToUint((u8**)data); + } + else { + // high nibble + readTypeInHighNbl; + packCount = varintToUint((u8**)data); + } + packedType = PK_BYTES; + } + + B = allocSBytes(); + count = varintToUint((u8**)data); + sBytesPushBuffer(&B, data, count); + *data += count; + sArrayPushTiny(array, (smallt *) B); + // stop unpacking when packCount == 0 + packCount--; + if (!packCount) inPack = false; + break; + case UNIFORM_DICT: + d = NULL; + uniformDictNetDeserial(&d, data, ctx, /*packed=*/false); + sArrayPushTiny(array, (smallt *) d); + break; + case UNIFORM_ARRAY: + a = NULL; + uniformArrayNetDeserial(&a, data, ctx, /*packed=*/false); + sArrayPushTiny(array, (smallt *) a); + break; + } + } +} + +internal void uniformArrayNetDeserial(sArrayt **array, u8 **data, contextt *ctx, bool packed) { + sUndefinedt *u = NULL; + sBoolt *bo = NULL; + double *D = NULL; + sDoublet *Do = NULL; + sDictt *d = NULL; + sIntt *io = NULL; + char *s = NULL; + sStringt *so = NULL; + sArrayt *a = NULL; + sBytest *B = NULL; + uint32_t count; + uint32_t arrayCount; + u8 type; + + if (packed) { + type = (**data) & 0xF; + arrayCount = netTypeVarintToUint(data); + } + else { + if (ctx->nibble == lowNbl) { + type = (**data) >> 4; + (*data)++; + arrayCount = varintToUint(data); + } + else { + readTypeInHighNbl; + type = (**data) & 0xF; + arrayCount = netTypeVarintToUint(data); + } + } + + if (!arrayCount) { + *array = allocSArray();; + ret; + } + + switch(type) { + case S_UNDEFINED: + loop(arrayCount) { + u = allocSUndefined(); + sArrayPushTiny(array, (smallt *) u); + } + break; + case S_BOOL: + loop(arrayCount) { + if (!ctx->boolAddr) { + read8bPackedBool; + ctx->boolShift = 0; + } + if (ctx->boolShift == 8) { + read8bPackedBool; + bo = allocSBool((*ctx->boolAddr) & 0x1); + } + else { + bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); + } + sArrayPushTiny(array, (smallt *) bo); + } + break; + case S_DICT: + loop(arrayCount) { + d = NULL; + dictNetDeserial(&d, data, ctx, /*packed=*/true); + sArrayPushTiny(array, (smallt *) d); + } + break; + case S_DOUBLE: + loop(arrayCount) { + D = (double *)(*data); + *data += sizeof(double); + Do = allocSDouble(*D); + sArrayPushTiny(array, (smallt *) Do); + } + break; + case S_INT: + loop(arrayCount) { + i64 v = varintToUint(data); + v = (v >> 1) ^ ((v << 63) >> 63); + io = allocSInt(v); + sArrayPushTiny(array, (smallt *) io); + } + break; + case S_STRING: + loop(arrayCount) { + s = (char *)(*data); + *data += strlen(s)+1; + so = allocSStringTiny(s); + sArrayPushTiny(array, (smallt *) so); + } + break; + case S_ARRAY: + loop(arrayCount) { + a = NULL; + arrayNetDeserial(&a, data, ctx, /*packed=*/true); + sArrayPushTiny(array, (smallt *) a); + } + break; + case S_BYTES: + loop(arrayCount) { + B = allocSBytes(); + count = varintToUint((u8**)data); + sBytesPushBuffer(&B, data, count); + *data += count; + sArrayPushTiny(array, (smallt *) B); + } + break; + case UNIFORM_DICT: + loop(arrayCount) { + d = NULL; + uniformDictNetDeserial(&d, data, ctx, /*packed=*/true); + sArrayPushTiny(array, (smallt *) d); + } + break; + case UNIFORM_ARRAY: + loop(arrayCount) { + a = NULL; + uniformArrayNetDeserial(&a, data, ctx, /*packed=*/true); + sArrayPushTiny(array, (smallt *) a); + } + break; + } +} + +internal smallJsont* deserialNetSerial(smallJsont *self, smallBytest *data) { + + if (!data) { + ret self; + } + + smallt *o = netDeserial(data->B); + + if (!o) { + ret self; + } + + freeG(self); + + setsoG(self, o); + + ret self; +} + +// vim: set expandtab ts=2 sw=2: diff --git a/netSerial.c.gcov b/netSerial.c.gcov @@ -0,0 +1,7713 @@ + -: 0:Source:/home/remy/git/sw/sheepyPackagesGitHub/netSerial/netSerial.c + -: 0:Graph:netSerial.gcno + -: 0:Data:netSerial.gcda + -: 0:Runs:7 + -: 0:Programs:1 + -: 1: + -: 2:#include "libsheepyObject.h" + -: 3:#include "netSerial.h" + -: 4:#include "netSerialInternal.h" + -: 5: + -: 6:#include <stdlib.h> + -: 7:#include <string.h> + -: 8:#include <stdio.h> + -: 9: + -: 10:#define lv logVarG + -: 11: + -: 12:void initiateNetSerialLevel0(smallJsont *self); + -: 13:void initiateNetSerialLevel1(smallJsont *self); + -: 14:void initiateNetSerialLevel2(smallJsont *self); + -: 15:void initiateNetSerial(smallJsont *self); + -: 16:void registerMethodsNetSerialLevel0(smallJsonFunctionst *f); + -: 17:void registerMethodsNetSerialLevel1(smallJsonFunctionst *f); + -: 18:void registerMethodsNetSerialLevel2(smallJsonFunctionst *f); + -: 19:void registerMethodsNetSerial(smallJsonFunctionst *f); + -: 20:void initiateAllocateNetSerialLevel0(smallJsont **self); + -: 21:void initiateAllocateNetSerialLevel1(smallJsont **self); + -: 22:void initiateAllocateNetSerialLevel2(smallJsont **self); + -: 23:void initiateAllocateNetSerial(smallJsont **self); + -: 24:void finalizeNetSerial(void); + -: 25:smallJsont* allocNetSerialLevel0(void); + -: 26:smallJsont* allocNetSerialLevel1(void); + -: 27:smallJsont* allocNetSerialLevel2(void); + -: 28:smallJsont* allocNetSerial(void); + -: 29:internal const char* helpNetSerial(smallJsont *self); + -: 30:internal smallBytest* serialNetSerialLevel0(smallJsont *self); + -: 31:internal smallBytest* serialNetSerialLevel1(smallJsont *self); + -: 32:internal smallBytest* serialNetSerialLevel2(smallJsont *self); + -: 33:internal smallBytest* serialNetSerial(smallJsont *self); + -: 34:internal smallJsont* deserialNetSerialLevel0(smallJsont *self, smallBytest *data); + -: 35:internal smallJsont* deserialNetSerialLevel1(smallJsont *self, smallBytest *data); + -: 36:internal smallJsont* deserialNetSerialLevel2(smallJsont *self, smallBytest *data); + -: 37:internal smallJsont* deserialNetSerial(smallJsont *self, smallBytest *data); + -: 38: + -: 39:internal void uintToNetTypeVarint(sBytest **buf, u8 type, u64 value); + -: 40:internal void uintToVarint(sBytest **buf, u64 value); + -: 41:internal u64 netTypeVarintToUint(u8 **buf); + -: 42:internal u64 varintToUint(u8 **buf); + -: 43: + -: 44:internal sBytest* netSerialLevel0(smallt *o); + -: 45:internal void dictNetSerialLevel0(sBytest **r, sDictt *dict); + -: 46:internal void arrayNetSerialLevel0(sBytest **r, sArrayt *array); + -: 47:internal sBytest* netSerialLevel1(smallt *o); + -: 48:internal void dictNetSerialLevel1(sBytest **r, sDictt *dict, contextt *ctx); + -: 49:internal void arrayNetSerialLevel1(sBytest **r, sArrayt *array, contextt *ctx); + -: 50:internal sBytest* netSerialLevel2(smallt *o); + -: 51:internal void dictNetSerialLevel2(sBytest **r, sDictt *dict, contextt *ctx, bool packed); + -: 52:internal void arrayNetSerialLevel2(sBytest **r, sArrayt *array, contextt *ctx, bool packed); + -: 53:internal sBytest* netSerial(smallt *o); + -: 54:internal void dictNetSerial(sBytest **r, sDictt *dict, contextt *ctx, packingT packing); + -: 55:internal void arrayNetSerial(sBytest **r, sArrayt *array, contextt *ctx, packingT packing); + -: 56: + -: 57:internal smallt* netDeserialLevel0(sBytest *obj); + -: 58:internal void dictNetDeserialLevel0(sDictt **dict, char **data); + -: 59:internal void arrayNetDeserialLevel0(sArrayt **array, char **data); + -: 60:internal smallt* netDeserialLevel1(sBytest *obj); + -: 61:internal void dictNetDeserialLevel1(sDictt **dict, u8 **data, contextt *ctx); + -: 62:internal void arrayNetDeserialLevel1(sArrayt **array, u8 **data, contextt *ctx); + -: 63:internal smallt* netDeserialLevel2(sBytest *obj); + -: 64:internal void dictNetDeserialLevel2(sDictt **dict, u8 **data, contextt *ctx, bool packed); + -: 65:internal u8 isDictUniform(sDictt *dict); + -: 66:internal u8 isArrayUniform(sArrayt *array); + -: 67:internal void uniformDictNetDeserialLevel2(sDictt **dict, u8 **data, contextt *ctx, bool packed); + -: 68:internal void arrayNetDeserialLevel2(sArrayt **array, u8 **data, contextt *ctx, bool packed); + -: 69:internal void uniformArrayNetDeserialLevel2(sArrayt **array, u8 **data, contextt *ctx, bool packed); + -: 70:internal smallt* netDeserial(sBytest *obj); + -: 71:internal void dictNetDeserial(sDictt **dict, u8 **data, contextt *ctx, bool packed); + -: 72:internal void uniformDictNetDeserial(sDictt **dict, u8 **data, contextt *ctx, bool packed); + -: 73:internal void arrayNetDeserial(sArrayt **array, u8 **data, contextt *ctx, bool packed); + -: 74:internal void uniformArrayNetDeserial(sArrayt **array, u8 **data, contextt *ctx, bool packed); + -: 75: + -: 76:/* enable/disable logging */ + -: 77:/* #undef pLog */ + -: 78:/* #define pLog(...) */ + -: 79: +function initiateNetSerialLevel0 called 0 returned 0% blocks executed 0% + #####: 80:void initiateNetSerialLevel0(smallJsont *self) { + -: 81: + #####: 82: initiateSmallJson(self); +call 0 never executed + -: 83: + #####: 84: self->type = "netSerial"; + #####: 85: if (!netSerialF) { +branch 0 never executed +branch 1 never executed + #####: 86: netSerialF = malloc(sizeof(smallJsonFunctionst)); + #####: 87: registerMethodsNetSerialLevel0(netSerialF); +call 0 never executed + #####: 88: pErrorNot0(atexit(finalizeNetSerial)); +call 0 never executed +branch 1 never executed +branch 2 never executed +call 3 never executed +branch 4 never executed +branch 5 never executed +call 6 never executed +branch 7 never executed +branch 8 never executed +call 9 never executed +call 10 never executed +call 11 never executed +call 12 never executed + -: 89: } + #####: 90: self->f = netSerialF; + #####: 91:} + -: 92: +function initiateNetSerialLevel1 called 0 returned 0% blocks executed 0% + #####: 93:void initiateNetSerialLevel1(smallJsont *self) { + -: 94: + #####: 95: initiateSmallJson(self); +call 0 never executed + -: 96: + #####: 97: self->type = "netSerial"; + #####: 98: if (!netSerialF) { +branch 0 never executed +branch 1 never executed + #####: 99: netSerialF = malloc(sizeof(smallJsonFunctionst)); + #####: 100: registerMethodsNetSerialLevel1(netSerialF); +call 0 never executed + #####: 101: pErrorNot0(atexit(finalizeNetSerial)); +call 0 never executed +branch 1 never executed +branch 2 never executed +call 3 never executed +branch 4 never executed +branch 5 never executed +call 6 never executed +branch 7 never executed +branch 8 never executed +call 9 never executed +call 10 never executed +call 11 never executed +call 12 never executed + -: 102: } + #####: 103: self->f = netSerialF; + #####: 104:} + -: 105: +function initiateNetSerialLevel2 called 0 returned 0% blocks executed 0% + #####: 106:void initiateNetSerialLevel2(smallJsont *self) { + -: 107: + #####: 108: initiateSmallJson(self); +call 0 never executed + -: 109: + #####: 110: self->type = "netSerial"; + #####: 111: if (!netSerialF) { +branch 0 never executed +branch 1 never executed + #####: 112: netSerialF = malloc(sizeof(smallJsonFunctionst)); + #####: 113: registerMethodsNetSerialLevel2(netSerialF); +call 0 never executed + #####: 114: pErrorNot0(atexit(finalizeNetSerial)); +call 0 never executed +branch 1 never executed +branch 2 never executed +call 3 never executed +branch 4 never executed +branch 5 never executed +call 6 never executed +branch 7 never executed +branch 8 never executed +call 9 never executed +call 10 never executed +call 11 never executed +call 12 never executed + -: 115: } + #####: 116: self->f = netSerialF; + #####: 117:} + -: 118: +function initiateNetSerial called 12 returned 100% blocks executed 43% + 12: 119:void initiateNetSerial(smallJsont *self) { + -: 120: + 12: 121: initiateSmallJson(self); +call 0 returned 100% + -: 122: + 12: 123: self->type = "netSerial"; + 12: 124: if (!netSerialF) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 6: 125: netSerialF = malloc(sizeof(smallJsonFunctionst)); + 6: 126: registerMethodsNetSerial(netSerialF); +call 0 returned 100% + 6: 127: pErrorNot0(atexit(finalizeNetSerial)); +call 0 returned 100% +branch 1 taken 0% (fallthrough) +branch 2 taken 100% +call 3 never executed +branch 4 never executed +branch 5 never executed +call 6 never executed +branch 7 never executed +branch 8 never executed +call 9 never executed +call 10 never executed +call 11 never executed +call 12 never executed + -: 128: } + 12: 129: self->f = netSerialF; + 12: 130:} + -: 131: +function registerMethodsNetSerialLevel0 called 0 returned 0% blocks executed 0% + #####: 132:void registerMethodsNetSerialLevel0(smallJsonFunctionst *f) { + -: 133: + #####: 134: registerMethodsSmallJson(f); +call 0 never executed + #####: 135: f->help = helpNetSerial; + #####: 136: f->serial = serialNetSerialLevel0; + #####: 137: f->deserial = deserialNetSerialLevel0; + #####: 138:} + -: 139: +function registerMethodsNetSerialLevel1 called 0 returned 0% blocks executed 0% + #####: 140:void registerMethodsNetSerialLevel1(smallJsonFunctionst *f) { + -: 141: + #####: 142: registerMethodsSmallJson(f); +call 0 never executed + #####: 143: f->help = helpNetSerial; + #####: 144: f->serial = serialNetSerialLevel1; + #####: 145: f->deserial = deserialNetSerialLevel1; + #####: 146:} + -: 147: +function registerMethodsNetSerialLevel2 called 0 returned 0% blocks executed 0% + #####: 148:void registerMethodsNetSerialLevel2(smallJsonFunctionst *f) { + -: 149: + #####: 150: registerMethodsSmallJson(f); +call 0 never executed + #####: 151: f->help = helpNetSerial; + #####: 152: f->serial = serialNetSerialLevel2; + #####: 153: f->deserial = deserialNetSerialLevel2; + #####: 154:} + -: 155: +function registerMethodsNetSerial called 6 returned 100% blocks executed 100% + 6: 156:void registerMethodsNetSerial(smallJsonFunctionst *f) { + -: 157: + 6: 158: registerMethodsSmallJson(f); +call 0 returned 100% + 6: 159: f->help = helpNetSerial; + 6: 160: f->serial = serialNetSerial; + 6: 161: f->deserial = deserialNetSerial; + 6: 162:} + -: 163: +function initiateAllocateNetSerialLevel0 called 0 returned 0% blocks executed 0% + #####: 164:void initiateAllocateNetSerialLevel0(smallJsont **self) { + -: 165: + #####: 166: if (self) { +branch 0 never executed +branch 1 never executed + #####: 167: (*self) = malloc(sizeof(smallJsont)); + #####: 168: if (*self) { +branch 0 never executed +branch 1 never executed + #####: 169: initiateNetSerialLevel0(*self); +call 0 never executed + -: 170: } + -: 171: } + #####: 172:} + -: 173: +function initiateAllocateNetSerialLevel1 called 0 returned 0% blocks executed 0% + #####: 174:void initiateAllocateNetSerialLevel1(smallJsont **self) { + -: 175: + #####: 176: if (self) { +branch 0 never executed +branch 1 never executed + #####: 177: (*self) = malloc(sizeof(smallJsont)); + #####: 178: if (*self) { +branch 0 never executed +branch 1 never executed + #####: 179: initiateNetSerialLevel1(*self); +call 0 never executed + -: 180: } + -: 181: } + #####: 182:} + -: 183: +function initiateAllocateNetSerialLevel2 called 0 returned 0% blocks executed 0% + #####: 184:void initiateAllocateNetSerialLevel2(smallJsont **self) { + -: 185: + #####: 186: if (self) { +branch 0 never executed +branch 1 never executed + #####: 187: (*self) = malloc(sizeof(smallJsont)); + #####: 188: if (*self) { +branch 0 never executed +branch 1 never executed + #####: 189: initiateNetSerialLevel2(*self); +call 0 never executed + -: 190: } + -: 191: } + #####: 192:} + -: 193: +function initiateAllocateNetSerial called 0 returned 0% blocks executed 0% + #####: 194:void initiateAllocateNetSerial(smallJsont **self) { + -: 195: + #####: 196: if (self) { +branch 0 never executed +branch 1 never executed + #####: 197: (*self) = malloc(sizeof(smallJsont)); + #####: 198: if (*self) { +branch 0 never executed +branch 1 never executed + #####: 199: initiateNetSerial(*self); +call 0 never executed + -: 200: } + -: 201: } + #####: 202:} + -: 203: +function finalizeNetSerial called 6 returned 100% blocks executed 100% + 6: 204:void finalizeNetSerial(void) { + -: 205: + 6: 206: if (netSerialF) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 6: 207: free(netSerialF); + 6: 208: netSerialF = NULL; + -: 209: } + 6: 210:} + -: 211: +function allocNetSerialLevel0 called 0 returned 0% blocks executed 0% + #####: 212:smallJsont* allocNetSerialLevel0(void) { + #####: 213: smallJsont *r = NULL; + -: 214: + #####: 215: initiateAllocateNetSerialLevel0(&r); +call 0 never executed + #####: 216: ret r; + -: 217:} + -: 218: +function allocNetSerialLevel1 called 0 returned 0% blocks executed 0% + #####: 219:smallJsont* allocNetSerialLevel1(void) { + #####: 220: smallJsont *r = NULL; + -: 221: + #####: 222: initiateAllocateNetSerialLevel1(&r); +call 0 never executed + #####: 223: ret r; + -: 224:} + -: 225: +function allocNetSerialLevel2 called 0 returned 0% blocks executed 0% + #####: 226:smallJsont* allocNetSerialLevel2(void) { + #####: 227: smallJsont *r = NULL; + -: 228: + #####: 229: initiateAllocateNetSerialLevel2(&r); +call 0 never executed + #####: 230: ret r; + -: 231:} + -: 232: +function allocNetSerial called 0 returned 0% blocks executed 0% + #####: 233:smallJsont* allocNetSerial(void) { + #####: 234: smallJsont *r = NULL; + -: 235: + #####: 236: initiateAllocateNetSerial(&r); +call 0 never executed + #####: 237: ret r; + -: 238:} + -: 239: + -: 240: +function helpNetSerial called 0 returned 0% blocks executed 0% + #####: 241:internal const char* helpNetSerial(smallJsont UNUSED *self) { + #####: 242: ret "TODO helpNetSerial \n" helpTextSmallJson; + -: 243:} + -: 244: +function uintToNetTypeVarint called 105 returned 100% blocks executed 100% + 105: 245:internal void uintToNetTypeVarint(sBytest **buf, u8 type, u64 value) { + 105: 246: u64 c = value; + -: 247: /* encode b0..2 */ + 105: 248: u8 b = type + ((c & 0x7) << 4); + 105: 249: if (c & 0xFFFFFFFFFFFFFFF8) { +branch 0 taken 10% (fallthrough) +branch 1 taken 90% + 10: 250: b |= 0x80; + 10: 251: sBytesPush(buf, b); +call 0 returned 100% + 10: 252: c >>=3; + -: 253: /* encode b3..9 ...*/ + 31: 254: while(c) { +branch 0 taken 52% +branch 1 taken 48% + 11: 255: b = c & 0x7F; + 11: 256: if (c & 0xFFFFFFFFFFFFFF80) +branch 0 taken 9% (fallthrough) +branch 1 taken 91% + 1: 257: b |= 0x80; + 11: 258: sBytesPush(buf, b); +call 0 returned 100% + 11: 259: c >>=7; + -: 260: } + -: 261: } + -: 262: else + 95: 263: sBytesPush(buf, b); +call 0 returned 100% + 105: 264:} + -: 265: +function uintToVarint called 173 returned 100% blocks executed 90% + 173: 266:internal void uintToVarint(sBytest **buf, u64 value) { + 173: 267: u64 c = value; + 173: 268: u8 b = c & 0x7F; + 173: 269: if (c & 0xFFFFFFFFFFFFFF80) { +branch 0 taken 2% (fallthrough) +branch 1 taken 98% + 3: 270: b |= 0x80; + 3: 271: sBytesPush(buf, b); +call 0 returned 100% + 3: 272: c >>=7; + -: 273: /* encode b7..14 ...*/ + 9: 274: while(c) { +branch 0 taken 50% +branch 1 taken 50% + 3: 275: b = c & 0x7F; + 3: 276: if (c & 0xFFFFFFFFFFFFFF80) +branch 0 taken 0% (fallthrough) +branch 1 taken 100% + #####: 277: b |= 0x80; + 3: 278: sBytesPush(buf, b); +call 0 returned 100% + 3: 279: c >>=7; + -: 280: } + -: 281: } + -: 282: else + 170: 283: sBytesPush(buf, b); +call 0 returned 100% + 173: 284:} + -: 285: +function netTypeVarintToUint called 105 returned 100% blocks executed 100% + 105: 286:internal u64 netTypeVarintToUint(u8 **buf) { + 105: 287: u64 r = 0; + -: 288: + 105: 289: r = (**buf >> 4) & 0x7; + -: 290: + 105: 291: u8 c = 0; + 221: 292: while (**buf & 0x80) { +branch 0 taken 9% +branch 1 taken 91% (fallthrough) + 11: 293: (*buf)++; + 11: 294: r |= (**buf & 0x7F) << (7*c+3); + 11: 295: c++; + -: 296: } + 105: 297: (*buf)++; + 105: 298: ret r; + -: 299:} + -: 300: +function varintToUint called 173 returned 100% blocks executed 100% + 173: 301:internal u64 varintToUint(u8 **buf) { + 173: 302: u64 r = 0; + -: 303: + 173: 304: r = (**buf) & 0x7F; + 173: 305: u8 c = 1; + 349: 306: while (**buf & 0x80) { +branch 0 taken 2% +branch 1 taken 98% (fallthrough) + 3: 307: (*buf)++; + 3: 308: r |= (**buf & 0x7F) << (7*c); + 3: 309: c++; + -: 310: } + 173: 311: (*buf)++; + 173: 312: ret r; + -: 313:} + -: 314: + -: 315:// ------------------------------------- + -: 316:// Serializers + -: 317: +function netSerialLevel0 called 0 returned 0% blocks executed 0% + #####: 318:internal sBytest* netSerialLevel0(smallt *o) { + #####: 319: sBytest *r = NULL; + #####: 320: sBytest *B = NULL; + -: 321: + #####: 322: switch(o->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed +branch 9 never executed + -: 323: case UNDEFINED: + #####: 324: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 never executed + #####: 325: break; + -: 326: case BOOL: { + #####: 327: u8 c = NET_SERIAL_TYPES[(u8)o->type]; + -: 328: // set bit 4 when true + #####: 329: if (((sBoolt *)&(o->type))->value) +branch 0 never executed +branch 1 never executed + #####: 330: c |= (1<<4); + #####: 331: sBytesPush(&r, c); +call 0 never executed + -: 332: } + #####: 333: break; + -: 334: case CONTAINER: + -: 335: // undefined + #####: 336: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 never executed + #####: 337: break; + -: 338: case DICT: + #####: 339: dictNetSerialLevel0(&r, (sDictt *)&(o->type)); +call 0 never executed + #####: 340: break; + -: 341: case DOUBLE: + #####: 342: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 never executed + #####: 343: sBytesPushBuffer(&r, &((sDoublet *)&(o->type))->value, sizeof(double)); +call 0 never executed + #####: 344: break; + -: 345: case INT: { + -: 346: // encode int to varint + -: 347: // v is int64_t to convert to varint + #####: 348: i64 v = ((sIntt *)&(o->type))->value; + -: 349: // encode v with arithmetic shifts + #####: 350: uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], (v << 1) ^ (v >> 63)); +call 0 never executed + -: 351: } + #####: 352: break; + -: 353: case STRING: + #####: 354: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 never executed + #####: 355: sBytesPushBuffer(&r, &((sStringt *)&(o->type))->data, sizeof(sStringt) + strlen(&(((sStringt *)&(o->type))->data)) -1); +call 0 never executed + #####: 356: break; + -: 357: case ARRAY: + #####: 358: arrayNetSerialLevel0(&r, (sArrayt *)&(o->type)); +call 0 never executed + #####: 359: break; + -: 360: case BYTES: + #####: 361: B = (sBytest *)&(o->type); + #####: 362: uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], B->count); +call 0 never executed + #####: 363: sBytesPushBuffer(&r, &(B->data), B->count); +call 0 never executed + #####: 364: break; + -: 365: } + #####: 366: ret r; + -: 367:} + -: 368: + -: 369:/** + -: 370: * serialize dictionary + -: 371: * + -: 372: * the serialized dict is pushed to r. + -: 373: * All elements are serialized recursively + -: 374: * + -: 375: * the data in containers is not serialized + -: 376: * + -: 377: * \param + -: 378: * r small bytes object + -: 379: * dict dictionary to serialize + -: 380: */ +function dictNetSerialLevel0 called 0 returned 0% blocks executed 0% + #####: 381:internal void dictNetSerialLevel0(sBytest **r, sDictt *dict) { + #####: 382: sBytest *B = NULL; + -: 383: + #####: 384: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)dict->type], dict->count); +call 0 never executed + -: 385: + #####: 386: forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 387: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 388: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + -: 389: + #####: 390: switch(e->data->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed +branch 9 never executed + -: 391: case UNDEFINED: + #####: 392: sBytesPush(r, NET_SERIAL_TYPES[(u8)e->data->type]); +call 0 never executed + #####: 393: break; + -: 394: case BOOL: { + #####: 395: u8 c = NET_SERIAL_TYPES[(u8)e->data->type]; + -: 396: // set bit 4 when true + #####: 397: if (((sBoolt *)(e->data))->value) +branch 0 never executed +branch 1 never executed + #####: 398: c |= (1<<4); + #####: 399: sBytesPush(r, c); +call 0 never executed + -: 400: } + #####: 401: break; + -: 402: case CONTAINER: + -: 403: // undefined + #####: 404: sBytesPush(r, NET_SERIAL_TYPES[(u8)e->data->type]); +call 0 never executed + #####: 405: break; + -: 406: case DICT: + #####: 407: dictNetSerialLevel0(r, (sDictt *)(e->data)); +call 0 never executed + #####: 408: break; + -: 409: case DOUBLE: + #####: 410: sBytesPush(r, NET_SERIAL_TYPES[(u8)e->data->type]); +call 0 never executed + #####: 411: sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); +call 0 never executed + #####: 412: break; + -: 413: case INT: { + -: 414: // encode int to varint + -: 415: // v is int64_t to convert to varint + #####: 416: i64 v = ((sIntt *)(e->data))->value; + -: 417: // encode v with arithmetic shifts + #####: 418: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], (v << 1) ^ (v >> 63)); +call 0 never executed + -: 419: } + #####: 420: break; + -: 421: case STRING: + #####: 422: sBytesPush(r, NET_SERIAL_TYPES[(u8)e->data->type]); +call 0 never executed + #####: 423: sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); +call 0 never executed + #####: 424: break; + -: 425: case ARRAY: + #####: 426: arrayNetSerialLevel0(r, (sArrayt *)(e->data)); +call 0 never executed + #####: 427: break; + -: 428: case BYTES: + #####: 429: B = (sBytest *)(e->data); + #####: 430: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], B->count); +call 0 never executed + #####: 431: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + #####: 432: break; + -: 433: } + -: 434: } + -: 435: } + #####: 436: ret; + -: 437:} + -: 438: + -: 439:/** + -: 440: * serialize array + -: 441: * + -: 442: * the serialized array is pushed to r. + -: 443: * All elements are serialized recursively + -: 444: * + -: 445: * the data in containers is not serialized + -: 446: * + -: 447: * \param + -: 448: * r small bytes object + -: 449: * array to serialize + -: 450: */ +function arrayNetSerialLevel0 called 0 returned 0% blocks executed 0% + #####: 451:internal void arrayNetSerialLevel0(sBytest **r, sArrayt *array) { + #####: 452: sBytest *B = NULL; + -: 453: + #####: 454: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)array->type], array->count); +call 0 never executed + -: 455: + #####: 456: forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 457: if (!e) { +branch 0 never executed +branch 1 never executed + -: 458: // empty slots are represented as undefined elements + #####: 459: sBytesPush(r, NET_SERIAL_TYPES[UNDEFINED]); +call 0 never executed + -: 460: } + -: 461: else { + #####: 462: switch(e->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed +branch 9 never executed + -: 463: case UNDEFINED: + #####: 464: sBytesPush(r, NET_SERIAL_TYPES[(u8)e->type]); +call 0 never executed + #####: 465: break; + -: 466: case BOOL: { + #####: 467: u8 c = NET_SERIAL_TYPES[(u8)e->type]; + -: 468: // set bit 4 when true + #####: 469: if (((sBoolt *)&(e->type))->value) +branch 0 never executed +branch 1 never executed + #####: 470: c |= (1<<4); + #####: 471: sBytesPush(r, c); +call 0 never executed + -: 472: } + #####: 473: break; + -: 474: case CONTAINER: + -: 475: // undefined + #####: 476: sBytesPush(r, NET_SERIAL_TYPES[(u8)e->type]); +call 0 never executed + #####: 477: break; + -: 478: case DICT: + #####: 479: dictNetSerialLevel0(r, (sDictt *)e); +call 0 never executed + #####: 480: break; + -: 481: case DOUBLE: + #####: 482: sBytesPush(r, NET_SERIAL_TYPES[(u8)e->type]); +call 0 never executed + #####: 483: sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); +call 0 never executed + #####: 484: break; + -: 485: case INT: { + -: 486: // encode int to varint + -: 487: // v is int64_t to convert to varint + #####: 488: i64 v = ((sIntt *)&(e->type))->value; + -: 489: // encode v with arithmetic shifts + #####: 490: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], (v << 1) ^ (v >> 63)); +call 0 never executed + -: 491: } + #####: 492: break; + -: 493: case STRING: + #####: 494: sBytesPush(r, NET_SERIAL_TYPES[(u8)e->type]); +call 0 never executed + #####: 495: sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); +call 0 never executed + #####: 496: break; + -: 497: case ARRAY: + #####: 498: arrayNetSerialLevel0(r, (sArrayt *)e); +call 0 never executed + #####: 499: break; + -: 500: case BYTES: + #####: 501: B = (sBytest *)e; + #####: 502: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], B->count); +call 0 never executed + #####: 503: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + #####: 504: break; + -: 505: } + -: 506: } + -: 507: } + #####: 508: ret; + -: 509:} + -: 510: +function serialNetSerialLevel0 called 0 returned 0% blocks executed 0% + #####: 511:internal smallBytest* serialNetSerialLevel0(smallJsont *self) { + -: 512: + #####: 513: smallt *o = getsoG(self); +call 0 never executed + -: 514: + #####: 515: if (o == NULL) +branch 0 never executed +branch 1 never executed + #####: 516: ret NULL; + -: 517: + #####: 518: sBytest *B = netSerialLevel0(o); +call 0 never executed + -: 519: + #####: 520: if (!B) { +branch 0 never executed +branch 1 never executed + #####: 521: ret NULL; + -: 522: } + -: 523: + #####: 524: createAllocateSmallBytes(r); +call 0 never executed + #####: 525: r->B = B; + #####: 526: ret r; + -: 527:} + -: 528: + -: 529:// level 1 + -: 530: +function netSerialLevel1 called 0 returned 0% blocks executed 0% + #####: 531:internal sBytest* netSerialLevel1(smallt *o) { + #####: 532: sBytest *r = NULL; + #####: 533: sBytest *B = NULL; + #####: 534: contextt ctx = {.nibble=lowNbl, .nblOffset=0, .boolShift = 0, .boolOffset=0}; + -: 535: + #####: 536: switch(o->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 537: case UNDEFINED: + -: 538: case CONTAINER: + #####: 539: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 never executed + #####: 540: break; + -: 541: case BOOL: { + #####: 542: u8 c = NET_SERIAL_TYPES[(u8)o->type]; + -: 543: // set bit 4 when true + #####: 544: if (((sBoolt *)&(o->type))->value) +branch 0 never executed +branch 1 never executed + #####: 545: c |= (1<<4); + #####: 546: sBytesPush(&r, c); +call 0 never executed + -: 547: } + #####: 548: break; + -: 549: case DICT: + #####: 550: dictNetSerialLevel1(&r, (sDictt *)&(o->type), &ctx); +call 0 never executed + #####: 551: break; + -: 552: case DOUBLE: + #####: 553: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 never executed + #####: 554: sBytesPushBuffer(&r, &((sDoublet *)&(o->type))->value, sizeof(double)); +call 0 never executed + #####: 555: break; + -: 556: case INT: { + -: 557: // encode int to varint + -: 558: // v is int64_t to convert to varint + #####: 559: i64 v = ((sIntt *)&(o->type))->value; + -: 560: // encode v with arithmetic shifts + #####: 561: uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], (v << 1) ^ (v >> 63)); +call 0 never executed + -: 562: } + #####: 563: break; + -: 564: case STRING: + #####: 565: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 never executed + #####: 566: sBytesPushBuffer(&r, &((sStringt *)&(o->type))->data, sizeof(sStringt) + strlen(&(((sStringt *)&(o->type))->data)) -1); +call 0 never executed + #####: 567: break; + -: 568: case ARRAY: + #####: 569: arrayNetSerialLevel1(&r, (sArrayt *)&(o->type), &ctx); +call 0 never executed + #####: 570: break; + -: 571: case BYTES: + #####: 572: B = (sBytest *)&(o->type); + #####: 573: uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], B->count); +call 0 never executed + #####: 574: sBytesPushBuffer(&r, &(B->data), B->count); +call 0 never executed + #####: 575: break; + -: 576: } + #####: 577: ret r; + -: 578:} + -: 579: + -: 580:/** + -: 581: * serialize dictionary + -: 582: * + -: 583: * the serialized dict is pushed to r. + -: 584: * All elements are serialized recursively + -: 585: * + -: 586: * the data in containers is not serialized + -: 587: * + -: 588: * \param + -: 589: * r small bytes object + -: 590: * dict dictionary to serialize + -: 591: */ +function dictNetSerialLevel1 called 0 returned 0% blocks executed 0% + #####: 592:internal void dictNetSerialLevel1(sBytest **r, sDictt *dict, contextt *ctx) { + #####: 593: sBytest *B = NULL; + #####: 594: char *data = NULL; + -: 595: + #####: 596: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 597: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)dict->type], dict->count); +call 0 never executed + -: 598: } + -: 599: else { + -: 600: // high nibble + -: 601: #define storeTypeInHighNbl(o)\ + -: 602: ctx->nibble = lowNbl;\ + -: 603: data = (char *)&((*r)->data) + ctx->nblOffset;\ + -: 604: *data |= NET_SERIAL_TYPES[(u8)o->type] << 4 + #####: 605: storeTypeInHighNbl(dict); + #####: 606: uintToVarint(r, dict->count); +call 0 never executed + -: 607: } + -: 608: + #####: 609: forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 610: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 611: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + -: 612: + #####: 613: switch(e->data->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 614: case UNDEFINED: + -: 615: case CONTAINER: + #####: 616: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 617: #define storeTypeOnly(o)\ + -: 618: sBytesPush(r, NET_SERIAL_TYPES[(u8)o->type]);\ + -: 619: ctx->nibble = highNbl;\ + -: 620: ctx->nblOffset = (*r)->count -1 + #####: 621: storeTypeOnly(e->data); +call 0 never executed + -: 622: } + -: 623: else { + #####: 624: storeTypeInHighNbl(e->data); + -: 625: } + #####: 626: break; + -: 627: case BOOL: + #####: 628: if (!ctx->boolOffset) { +branch 0 never executed +branch 1 never executed + -: 629: // new packed bools + #####: 630: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 631: #define storeNew4bPackedBool(o)\ + -: 632: u8 c = NET_SERIAL_TYPES[(u8)o->type];\ + -: 633: /* set bit 4 when true */\ + -: 634: if (((sBoolt *)(o))->value)\ + -: 635: c |= (1<<4);\ + -: 636: sBytesPush(r, c);\ + -: 637: ctx->boolShift = 5;\ + -: 638: ctx->boolOffset = (*r)->count -1 + #####: 639: storeNew4bPackedBool(e->data); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 640: } + -: 641: else { + -: 642: // high nibble, next byte is packed bools + #####: 643: storeTypeInHighNbl(e->data); + -: 644: #define storeNew8bPackedBool(o)\ + -: 645: u8 c = 0;\ + -: 646: if (((sBoolt *)(o))->value)\ + -: 647: c = 1;\ + -: 648: sBytesPush(r, c);\ + -: 649: ctx->boolShift = 1;\ + -: 650: ctx->boolOffset = (*r)->count -1 + #####: 651: storeNew8bPackedBool(e->data); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 652: } + -: 653: } + -: 654: else { + -: 655: // there was a bool before this one, fill bits in nibbles + #####: 656: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 657: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + -: 658: // previous packed bool is full + -: 659: // this byte is the new packed bools + #####: 660: storeNew4bPackedBool(e->data); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 661: } + -: 662: else { + #####: 663: storeTypeOnly(e->data); +call 0 never executed + -: 664: #define storeBool(o)\ + -: 665: data = (char *)&((*r)->data) + ctx->boolOffset;\ + -: 666: if (((sBoolt *)(o))->value)\ + -: 667: *data |= 1 << ctx->boolShift;\ + -: 668: ctx->boolShift++ + #####: 669: storeBool(e->data); +branch 0 never executed +branch 1 never executed + -: 670: } + -: 671: } + -: 672: else { + -: 673: // high nibble + #####: 674: storeTypeInHighNbl(e->data); + #####: 675: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + -: 676: // previous packed bool is full + -: 677: // next byte is the new packed bools + #####: 678: storeNew8bPackedBool(e->data); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 679: } + -: 680: else { + #####: 681: storeBool(e->data); +branch 0 never executed +branch 1 never executed + -: 682: } + -: 683: } + -: 684: } + #####: 685: break; + -: 686: case DICT: + #####: 687: dictNetSerialLevel1(r, (sDictt *)(e->data), ctx); +call 0 never executed + #####: 688: break; + -: 689: case DOUBLE: + #####: 690: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 691: storeTypeOnly(e->data); +call 0 never executed + -: 692: } + -: 693: else { + -: 694: // high nibble + #####: 695: storeTypeInHighNbl(e->data); + -: 696: } + #####: 697: sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); +call 0 never executed + #####: 698: break; + -: 699: case INT: { + -: 700: // encode int to varint + -: 701: // v is int64_t to convert to varint + #####: 702: i64 v = ((sIntt *)(e->data))->value; + #####: 703: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 704: // encode v with arithmetic shifts + #####: 705: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], (v << 1) ^ (v >> 63)); +call 0 never executed + -: 706: } + -: 707: else { + -: 708: // high nibble + #####: 709: storeTypeInHighNbl(e->data); + #####: 710: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 never executed + -: 711: } + -: 712: } + #####: 713: break; + -: 714: case STRING: + #####: 715: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 716: storeTypeOnly(e->data); +call 0 never executed + -: 717: } + -: 718: else { + -: 719: // high nibble + #####: 720: storeTypeInHighNbl(e->data); + -: 721: } + #####: 722: sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); +call 0 never executed + #####: 723: break; + -: 724: case ARRAY: + #####: 725: arrayNetSerialLevel1(r, (sArrayt *)(e->data), ctx); +call 0 never executed + #####: 726: break; + -: 727: case BYTES: + #####: 728: B = (sBytest *)(e->data); + #####: 729: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 730: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], B->count); +call 0 never executed + -: 731: } + -: 732: else { + -: 733: // high nibble + #####: 734: storeTypeInHighNbl(e->data); + #####: 735: uintToVarint(r, B->count); +call 0 never executed + -: 736: } + #####: 737: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + #####: 738: break; + -: 739: } + -: 740: } + -: 741: } + #####: 742: ret; + -: 743:} + -: 744: + -: 745:/** + -: 746: * serialize array + -: 747: * + -: 748: * the serialized array is pushed to r. + -: 749: * All elements are serialized recursively + -: 750: * + -: 751: * the data in containers is not serialized + -: 752: * + -: 753: * \param + -: 754: * r small bytes object + -: 755: * array to serialize + -: 756: */ +function arrayNetSerialLevel1 called 0 returned 0% blocks executed 0% + #####: 757:internal void arrayNetSerialLevel1(sBytest **r, sArrayt *array, contextt *ctx) { + #####: 758: sBytest *B = NULL; + #####: 759: char *data = NULL; + -: 760: + #####: 761: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 762: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)array->type], array->count); +call 0 never executed + -: 763: } + -: 764: else { + -: 765: // high nibble + #####: 766: storeTypeInHighNbl(array); + #####: 767: uintToVarint(r, array->count); +call 0 never executed + -: 768: } + -: 769: + #####: 770: forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 771: if (!e) { +branch 0 never executed +branch 1 never executed + -: 772: // empty slots are represented as undefined elements + #####: 773: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 774: sBytesPush(r, NET_SERIAL_TYPES[UNDEFINED]); +call 0 never executed + #####: 775: ctx->nibble = highNbl; + #####: 776: ctx->nblOffset = (*r)->count -1; + -: 777: } + -: 778: else { + -: 779: // high nibble + #####: 780: ctx->nibble = lowNbl; + #####: 781: data = (char *)&((*r)->data) + ctx->nblOffset; + #####: 782: *data |= NET_SERIAL_TYPES[UNDEFINED] << 4; + -: 783: } + -: 784: } + -: 785: else { + #####: 786: switch(e->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 787: case UNDEFINED: + -: 788: case CONTAINER: + #####: 789: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 790: storeTypeOnly(e); +call 0 never executed + -: 791: } + -: 792: else { + -: 793: // high nibble + #####: 794: storeTypeInHighNbl(e); + -: 795: } + #####: 796: break; + -: 797: case BOOL: + #####: 798: if (!ctx->boolOffset) { +branch 0 never executed +branch 1 never executed + -: 799: // new packed bools + #####: 800: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 801: storeNew4bPackedBool(e); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 802: } + -: 803: else { + -: 804: // high nibble, next byte is packed bools + #####: 805: storeTypeInHighNbl(e); + #####: 806: storeNew8bPackedBool(e); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 807: } + -: 808: } + -: 809: else { + -: 810: // there was a bool before this one, fill bits in nibbles + #####: 811: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 812: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + -: 813: // previous packed bool is full + -: 814: // this byte is the new packed bools + #####: 815: storeNew4bPackedBool(e); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 816: } + -: 817: else { + #####: 818: storeTypeOnly(e); +call 0 never executed + #####: 819: storeBool(e); +branch 0 never executed +branch 1 never executed + -: 820: } + -: 821: } + -: 822: else { + -: 823: // high nibble + #####: 824: storeTypeInHighNbl(e); + #####: 825: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + -: 826: // previous packed bool is full + -: 827: // next byte is the new packed bools + #####: 828: storeNew8bPackedBool(e); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 829: } + -: 830: else { + #####: 831: storeBool(e); +branch 0 never executed +branch 1 never executed + -: 832: } + -: 833: } + -: 834: } + #####: 835: break; + -: 836: case DICT: + #####: 837: dictNetSerialLevel1(r, (sDictt *)e, ctx); +call 0 never executed + #####: 838: break; + -: 839: case DOUBLE: + #####: 840: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 841: storeTypeOnly(e); +call 0 never executed + -: 842: } + -: 843: else { + -: 844: // high nibble + #####: 845: storeTypeInHighNbl(e); + -: 846: } + #####: 847: sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); +call 0 never executed + #####: 848: break; + -: 849: case INT: { + -: 850: // encode int to varint + -: 851: // v is int64_t to convert to varint + #####: 852: i64 v = ((sIntt *)&(e->type))->value; + #####: 853: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 854: // encode v with arithmetic shifts + #####: 855: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], (v << 1) ^ (v >> 63)); +call 0 never executed + -: 856: } + -: 857: else { + -: 858: // high nibble + #####: 859: storeTypeInHighNbl(e); + #####: 860: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 never executed + -: 861: } + -: 862: } + #####: 863: break; + -: 864: case STRING: + #####: 865: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 866: storeTypeOnly(e); +call 0 never executed + -: 867: } + -: 868: else { + -: 869: // high nibble + #####: 870: storeTypeInHighNbl(e); + -: 871: } + #####: 872: sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); +call 0 never executed + #####: 873: break; + -: 874: case ARRAY: + #####: 875: arrayNetSerialLevel1(r, (sArrayt *)e, ctx); +call 0 never executed + #####: 876: break; + -: 877: case BYTES: + #####: 878: B = (sBytest *)e; + #####: 879: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 880: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], B->count); +call 0 never executed + -: 881: } + -: 882: else { + -: 883: // high nibble + #####: 884: storeTypeInHighNbl(e); + #####: 885: uintToVarint(r, B->count); +call 0 never executed + -: 886: } + #####: 887: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + #####: 888: break; + -: 889: } + -: 890: } + -: 891: } + #####: 892: ret; + -: 893:} + -: 894: +function serialNetSerialLevel1 called 0 returned 0% blocks executed 0% + #####: 895:internal smallBytest* serialNetSerialLevel1(smallJsont *self) { + -: 896: + #####: 897: smallt *o = getsoG(self); +call 0 never executed + -: 898: + #####: 899: if (o == NULL) +branch 0 never executed +branch 1 never executed + #####: 900: ret NULL; + -: 901: + #####: 902: sBytest *B = netSerialLevel1(o); +call 0 never executed + -: 903: + #####: 904: if (!B) { +branch 0 never executed +branch 1 never executed + #####: 905: ret NULL; + -: 906: } + -: 907: + #####: 908: createAllocateSmallBytes(r); +call 0 never executed + #####: 909: r->B = B; + #####: 910: ret r; + -: 911:} + -: 912: + -: 913:// level 2 + -: 914: +function netSerialLevel2 called 0 returned 0% blocks executed 0% + #####: 915:internal sBytest* netSerialLevel2(smallt *o) { + #####: 916: sBytest *r = NULL; + #####: 917: sBytest *B = NULL; + #####: 918: contextt ctx = {.nibble=lowNbl, .nblOffset=0, .boolShift = 0, .boolOffset=0}; + -: 919: + #####: 920: switch(o->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 921: case UNDEFINED: + -: 922: case CONTAINER: + #####: 923: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 never executed + #####: 924: break; + -: 925: case BOOL: { + #####: 926: u8 c = NET_SERIAL_TYPES[(u8)o->type]; + -: 927: // set bit 4 when true + #####: 928: if (((sBoolt *)&(o->type))->value) +branch 0 never executed +branch 1 never executed + #####: 929: c |= (1<<4); + #####: 930: sBytesPush(&r, c); +call 0 never executed + -: 931: } + #####: 932: break; + -: 933: case DICT: + #####: 934: dictNetSerialLevel2(&r, (sDictt *)&(o->type), &ctx, /*packed=*/false); +call 0 never executed + #####: 935: break; + -: 936: case DOUBLE: + #####: 937: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 never executed + #####: 938: sBytesPushBuffer(&r, &((sDoublet *)&(o->type))->value, sizeof(double)); +call 0 never executed + #####: 939: break; + -: 940: case INT: { + -: 941: // encode int to varint + -: 942: // v is int64_t to convert to varint + #####: 943: i64 v = ((sIntt *)&(o->type))->value; + -: 944: // encode v with arithmetic shifts + #####: 945: uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], (v << 1) ^ (v >> 63)); +call 0 never executed + -: 946: } + #####: 947: break; + -: 948: case STRING: + #####: 949: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 never executed + #####: 950: sBytesPushBuffer(&r, &((sStringt *)&(o->type))->data, sizeof(sStringt) + strlen(&(((sStringt *)&(o->type))->data)) -1); +call 0 never executed + #####: 951: break; + -: 952: case ARRAY: + #####: 953: arrayNetSerialLevel2(&r, (sArrayt *)&(o->type), &ctx, /*packed=*/false); +call 0 never executed + #####: 954: break; + -: 955: case BYTES: + #####: 956: B = (sBytest *)&(o->type); + #####: 957: uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], B->count); +call 0 never executed + #####: 958: sBytesPushBuffer(&r, &(B->data), B->count); +call 0 never executed + #####: 959: break; + -: 960: } + #####: 961: ret r; + -: 962:} + -: 963: +function isDictUniform called 31 returned 100% blocks executed 69% + 31: 964:internal u8 isDictUniform(sDictt *dict) { + 31: 965: bool allElementsHaveSameType = true; + 31: 966: bool foundFirstType = false; + 31: 967: u8 type = 0; + 62: 968: forEachSDict(dict, e) { +branch 0 taken 68% +branch 1 taken 32% (fallthrough) + 42: 969: if (e->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 42: 970: if (foundFirstType) { +branch 0 taken 40% (fallthrough) +branch 1 taken 60% + -: 971: u8 nextType; + 17: 972: switch(e->data->type) { +branch 0 taken 0% +branch 1 taken 0% +branch 2 taken 100% + -: 973: case DICT: + #####: 974: nextType = isDictUniform((sDictt*)e->data); +call 0 never executed + #####: 975: break; + -: 976: case ARRAY: + #####: 977: nextType = isArrayUniform((sArrayt*)e->data); +call 0 never executed + #####: 978: break; + -: 979: default: + 17: 980: nextType = NET_SERIAL_TYPES[(u8)e->data->type]; + -: 981: } + 17: 982: if (nextType != type) { +branch 0 taken 65% (fallthrough) +branch 1 taken 35% + 11: 983: allElementsHaveSameType = false; + 11: 984: break; + -: 985: } + -: 986: } + -: 987: else { + 25: 988: switch(e->data->type) { +branch 0 taken 0% +branch 1 taken 0% +branch 2 taken 100% + -: 989: case DICT: + #####: 990: type = isDictUniform((sDictt*)e->data); +call 0 never executed + #####: 991: break; + -: 992: case ARRAY: + #####: 993: type = isArrayUniform((sArrayt*)e->data); +call 0 never executed + #####: 994: break; + -: 995: default: + 25: 996: type = NET_SERIAL_TYPES[(u8)e->data->type]; + -: 997: } + 25: 998: foundFirstType = true; + -: 999: } + -: 1000: } + -: 1001: } + 31: 1002: if (allElementsHaveSameType) +branch 0 taken 65% (fallthrough) +branch 1 taken 35% + 20: 1003: type = UNIFORM_DICT; + -: 1004: else + 11: 1005: type = S_DICT; + 31: 1006: ret type; + -: 1007:} + -: 1008: +function isArrayUniform called 27 returned 100% blocks executed 58% + 27: 1009:internal u8 isArrayUniform(sArrayt *array) { + 27: 1010: bool allElementsHaveSameType = true; + 27: 1011: bool foundFirstType = false; + 27: 1012: char type = 0; + 77: 1013: forEachSArray(array, e) { +branch 0 taken 73% +branch 1 taken 27% (fallthrough) + 56: 1014: if (!e) { +branch 0 taken 0% (fallthrough) +branch 1 taken 100% + #####: 1015: if (foundFirstType) { +branch 0 never executed +branch 1 never executed + #####: 1016: if (type != S_UNDEFINED) { +branch 0 never executed +branch 1 never executed + #####: 1017: allElementsHaveSameType = false; + #####: 1018: break; + -: 1019: } + -: 1020: } + -: 1021: else { + #####: 1022: type = S_UNDEFINED; + #####: 1023: foundFirstType = true; + -: 1024: } + -: 1025: } + -: 1026: else { + 56: 1027: if (foundFirstType) { +branch 0 taken 57% (fallthrough) +branch 1 taken 43% + -: 1028: u8 nextType; + 32: 1029: switch(e->type) { +branch 0 taken 0% +branch 1 taken 0% +branch 2 taken 100% + -: 1030: case DICT: + #####: 1031: nextType = isDictUniform((sDictt*)e); +call 0 never executed + #####: 1032: break; + -: 1033: case ARRAY: + #####: 1034: nextType = isArrayUniform((sArrayt*)e); +call 0 never executed + #####: 1035: break; + -: 1036: default: + 32: 1037: nextType = NET_SERIAL_TYPES[(u8)e->type]; + -: 1038: } + 32: 1039: if (nextType != type) { +branch 0 taken 19% (fallthrough) +branch 1 taken 81% + 6: 1040: allElementsHaveSameType = false; + 6: 1041: break; + -: 1042: } + -: 1043: } + -: 1044: else { + 24: 1045: switch(e->type) { +branch 0 taken 0% +branch 1 taken 0% +branch 2 taken 100% + -: 1046: case DICT: + #####: 1047: type = isDictUniform((sDictt*)e); +call 0 never executed + #####: 1048: break; + -: 1049: case ARRAY: + #####: 1050: type = isArrayUniform((sArrayt*)e); +call 0 never executed + #####: 1051: break; + -: 1052: default: + 24: 1053: type = NET_SERIAL_TYPES[(u8)e->type]; + -: 1054: } + 24: 1055: foundFirstType = true; + -: 1056: } + -: 1057: } + -: 1058: } + 27: 1059: if (allElementsHaveSameType) +branch 0 taken 78% (fallthrough) +branch 1 taken 22% + 21: 1060: type = UNIFORM_ARRAY; + -: 1061: else + 6: 1062: type = S_ARRAY; + 27: 1063: ret type; + -: 1064:} + -: 1065: + -: 1066:/** + -: 1067: * serialize dictionary + -: 1068: * + -: 1069: * the serialized dict is pushed to r. + -: 1070: * All elements are serialized recursively + -: 1071: * + -: 1072: * the data in containers is not serialized + -: 1073: * + -: 1074: * \param + -: 1075: * r small bytes object + -: 1076: * dict dictionary to serialize + -: 1077: */ +function dictNetSerialLevel2 called 0 returned 0% blocks executed 0% + #####: 1078:internal void dictNetSerialLevel2(sBytest **r, sDictt *dict, contextt *ctx, bool packed) { + #####: 1079: sBytest *B = NULL; + #####: 1080: char *data = NULL; + -: 1081: + -: 1082: // check if all elements have same type + #####: 1083: bool allElementsHaveSameType = true; + #####: 1084: bool foundFirstType = false; + #####: 1085: char type = 0; + #####: 1086: {forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1087: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1088: if (foundFirstType) { +branch 0 never executed +branch 1 never executed + -: 1089: u8 nextType; + #####: 1090: switch(e->data->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed + -: 1091: case DICT: + #####: 1092: nextType = isDictUniform((sDictt*)e->data); +call 0 never executed + #####: 1093: break; + -: 1094: case ARRAY: + #####: 1095: nextType = isArrayUniform((sArrayt*)e->data); +call 0 never executed + #####: 1096: break; + -: 1097: default: + #####: 1098: nextType = NET_SERIAL_TYPES[(u8)e->data->type]; + -: 1099: } + #####: 1100: if (nextType != type) { +branch 0 never executed +branch 1 never executed + #####: 1101: allElementsHaveSameType = false; + #####: 1102: break; + -: 1103: } + -: 1104: } + -: 1105: else { + #####: 1106: switch(e->data->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed + -: 1107: case DICT: + #####: 1108: type = isDictUniform((sDictt*)e->data); +call 0 never executed + #####: 1109: break; + -: 1110: case ARRAY: + #####: 1111: type = isArrayUniform((sArrayt*)e->data); +call 0 never executed + #####: 1112: break; + -: 1113: default: + #####: 1114: type = NET_SERIAL_TYPES[(u8)e->data->type]; + -: 1115: } + #####: 1116: foundFirstType = true; + -: 1117: } + -: 1118: } + -: 1119: }} + -: 1120: + #####: 1121: if (allElementsHaveSameType) { +branch 0 never executed +branch 1 never executed + -: 1122: // pack dictionary + #####: 1123: if (packed) { +branch 0 never executed +branch 1 never executed + #####: 1124: uintToNetTypeVarint(r, type, dict->count); +call 0 never executed + -: 1125: } + -: 1126: else { + #####: 1127: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1128: sBytesPush(r, (type << 4) + UNIFORM_DICT); +call 0 never executed + #####: 1129: uintToVarint(r, dict->count); +call 0 never executed + -: 1130: } + -: 1131: else { + -: 1132: // high nibble + #####: 1133: ctx->nibble = lowNbl; + #####: 1134: data = (char *)&((*r)->data) + ctx->nblOffset; + #####: 1135: *data |= UNIFORM_DICT << 4; + #####: 1136: uintToNetTypeVarint(r, type, dict->count); +call 0 never executed + -: 1137: } + -: 1138: } + -: 1139: + #####: 1140: switch(type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 1141: case S_UNDEFINED: + #####: 1142: {forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1143: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1144: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + -: 1145: } + -: 1146: }} + -: 1147: + #####: 1148: break; + -: 1149: case S_BOOL: + #####: 1150: {forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1151: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1152: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + -: 1153: + #####: 1154: if (!ctx->boolOffset) { +branch 0 never executed +branch 1 never executed + -: 1155: // new packed bools + #####: 1156: storeNew8bPackedBool(e->data); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1157: } + -: 1158: else { + -: 1159: // there was a bool before this one, fill bits in nibbles + #####: 1160: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + -: 1161: // previous packed bool is full + -: 1162: // next byte is the new packed bools + #####: 1163: storeNew8bPackedBool(e->data); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1164: } + -: 1165: else { + #####: 1166: storeBool(e->data); +branch 0 never executed +branch 1 never executed + -: 1167: } + -: 1168: } + -: 1169: } + -: 1170: }} + #####: 1171: break; + -: 1172: case S_DICT: + -: 1173: case UNIFORM_DICT: + #####: 1174: {forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1175: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1176: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + #####: 1177: dictNetSerialLevel2(r, (sDictt *)(e->data), ctx, /*packed=*/true); +call 0 never executed + -: 1178: } + -: 1179: }} + #####: 1180: break; + -: 1181: case S_DOUBLE: + #####: 1182: {forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1183: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1184: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + #####: 1185: sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); +call 0 never executed + -: 1186: } + -: 1187: }} + #####: 1188: break; + -: 1189: case S_INT: + #####: 1190: {forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1191: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1192: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + #####: 1193: i64 v = ((sIntt *)(e->data))->value; + #####: 1194: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 never executed + -: 1195: } + -: 1196: }} + #####: 1197: break; + -: 1198: case S_STRING: + #####: 1199: {forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1200: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1201: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + #####: 1202: sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); +call 0 never executed + -: 1203: } + -: 1204: }} + #####: 1205: break; + -: 1206: case S_ARRAY: + -: 1207: case UNIFORM_ARRAY: + #####: 1208: {forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1209: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1210: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + #####: 1211: arrayNetSerialLevel2(r, (sArrayt *)(e->data), ctx, /*packed=*/true); +call 0 never executed + -: 1212: } + -: 1213: }} + #####: 1214: break; + -: 1215: case S_BYTES: + #####: 1216: {forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1217: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1218: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + #####: 1219: B = (sBytest *)(e->data); + #####: 1220: uintToVarint(r, B->count); +call 0 never executed + #####: 1221: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + -: 1222: } + -: 1223: }} + #####: 1224: break; + -: 1225: } + #####: 1226: ret; + -: 1227: } + -: 1228: + #####: 1229: if (packed) { +branch 0 never executed +branch 1 never executed + #####: 1230: uintToVarint(r, dict->count); +call 0 never executed + -: 1231: } + -: 1232: else { + #####: 1233: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1234: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)dict->type], dict->count); +call 0 never executed + -: 1235: } + -: 1236: else { + -: 1237: // high nibble + -: 1238:#define storeTypeInHighNbl(o)\ + -: 1239: ctx->nibble = lowNbl;\ + -: 1240: data = (char *)&((*r)->data) + ctx->nblOffset;\ + -: 1241: *data |= NET_SERIAL_TYPES[(u8)o->type] << 4 + #####: 1242: storeTypeInHighNbl(dict); + #####: 1243: uintToVarint(r, dict->count); +call 0 never executed + -: 1244: } + -: 1245: } + -: 1246: + #####: 1247: forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1248: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1249: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + -: 1250: + #####: 1251: switch(e->data->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 1252: case UNDEFINED: + -: 1253: case CONTAINER: + #####: 1254: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 1255: #define storeTypeOnly(o)\ + -: 1256: sBytesPush(r, NET_SERIAL_TYPES[(u8)o->type]);\ + -: 1257: ctx->nibble = highNbl;\ + -: 1258: ctx->nblOffset = (*r)->count -1 + #####: 1259: storeTypeOnly(e->data); +call 0 never executed + -: 1260: } + -: 1261: else { + #####: 1262: storeTypeInHighNbl(e->data); + -: 1263: } + #####: 1264: break; + -: 1265: case BOOL: + #####: 1266: if (!ctx->boolOffset) { +branch 0 never executed +branch 1 never executed + -: 1267: // new packed bools + #####: 1268: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 1269: #define storeNew4bPackedBool(o)\ + -: 1270: u8 c = NET_SERIAL_TYPES[(u8)o->type];\ + -: 1271: /* set bit 4 when true */\ + -: 1272: if (((sBoolt *)(o))->value)\ + -: 1273: c |= (1<<4);\ + -: 1274: sBytesPush(r, c);\ + -: 1275: ctx->boolShift = 5;\ + -: 1276: ctx->boolOffset = (*r)->count -1 + #####: 1277: storeNew4bPackedBool(e->data); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1278: } + -: 1279: else { + -: 1280: // high nibble, next byte is packed bools + #####: 1281: storeTypeInHighNbl(e->data); + -: 1282: #define storeNew8bPackedBool(o)\ + -: 1283: u8 c = 0;\ + -: 1284: if (((sBoolt *)(o))->value)\ + -: 1285: c = 1;\ + -: 1286: sBytesPush(r, c);\ + -: 1287: ctx->boolShift = 1;\ + -: 1288: ctx->boolOffset = (*r)->count -1 + #####: 1289: storeNew8bPackedBool(e->data); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1290: } + -: 1291: } + -: 1292: else { + -: 1293: // there was a bool before this one, fill bits in nibbles + #####: 1294: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1295: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + -: 1296: // previous packed bool is full + -: 1297: // this byte is the new packed bools + #####: 1298: storeNew4bPackedBool(e->data); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1299: } + -: 1300: else { + #####: 1301: storeTypeOnly(e->data); +call 0 never executed + -: 1302: #define storeBool(o)\ + -: 1303: data = (char *)&((*r)->data) + ctx->boolOffset;\ + -: 1304: if (((sBoolt *)(o))->value)\ + -: 1305: *data |= 1 << ctx->boolShift;\ + -: 1306: ctx->boolShift++ + #####: 1307: storeBool(e->data); +branch 0 never executed +branch 1 never executed + -: 1308: } + -: 1309: } + -: 1310: else { + -: 1311: // high nibble + #####: 1312: storeTypeInHighNbl(e->data); + #####: 1313: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + -: 1314: // previous packed bool is full + -: 1315: // next byte is the new packed bools + #####: 1316: storeNew8bPackedBool(e->data); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1317: } + -: 1318: else { + #####: 1319: storeBool(e->data); +branch 0 never executed +branch 1 never executed + -: 1320: } + -: 1321: } + -: 1322: } + #####: 1323: break; + -: 1324: case DICT: + #####: 1325: dictNetSerialLevel2(r, (sDictt *)(e->data), ctx, /*packed=*/false); +call 0 never executed + #####: 1326: break; + -: 1327: case DOUBLE: + #####: 1328: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1329: storeTypeOnly(e->data); +call 0 never executed + -: 1330: } + -: 1331: else { + -: 1332: // high nibble + #####: 1333: storeTypeInHighNbl(e->data); + -: 1334: } + #####: 1335: sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); +call 0 never executed + #####: 1336: break; + -: 1337: case INT: { + -: 1338: // encode int to varint + -: 1339: // v is int64_t to convert to varint + #####: 1340: i64 v = ((sIntt *)(e->data))->value; + #####: 1341: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 1342: // encode v with arithmetic shifts + #####: 1343: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], (v << 1) ^ (v >> 63)); +call 0 never executed + -: 1344: } + -: 1345: else { + -: 1346: // high nibble + #####: 1347: storeTypeInHighNbl(e->data); + #####: 1348: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 never executed + -: 1349: } + -: 1350: } + #####: 1351: break; + -: 1352: case STRING: + #####: 1353: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1354: storeTypeOnly(e->data); +call 0 never executed + -: 1355: } + -: 1356: else { + -: 1357: // high nibble + #####: 1358: storeTypeInHighNbl(e->data); + -: 1359: } + #####: 1360: sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); +call 0 never executed + #####: 1361: break; + -: 1362: case ARRAY: + #####: 1363: arrayNetSerialLevel2(r, (sArrayt *)(e->data), ctx, /*packed=*/false); +call 0 never executed + #####: 1364: break; + -: 1365: case BYTES: + #####: 1366: B = (sBytest *)(e->data); + #####: 1367: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1368: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], B->count); +call 0 never executed + -: 1369: } + -: 1370: else { + -: 1371: // high nibble + #####: 1372: storeTypeInHighNbl(e->data); + #####: 1373: uintToVarint(r, B->count); +call 0 never executed + -: 1374: } + #####: 1375: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + #####: 1376: break; + -: 1377: } + -: 1378: } + -: 1379: } + #####: 1380: ret; + -: 1381:} + -: 1382: + -: 1383:/** + -: 1384: * serialize array + -: 1385: * + -: 1386: * the serialized array is pushed to r. + -: 1387: * All elements are serialized recursively + -: 1388: * + -: 1389: * the data in containers is not serialized + -: 1390: * + -: 1391: * \param + -: 1392: * r small bytes object + -: 1393: * array to serialize + -: 1394: */ +function arrayNetSerialLevel2 called 0 returned 0% blocks executed 0% + #####: 1395:internal void arrayNetSerialLevel2(sBytest **r, sArrayt *array, contextt *ctx, bool packed) { + #####: 1396: sBytest *B = NULL; + #####: 1397: char *data = NULL; + -: 1398: + -: 1399: // check if all elements have same type + #####: 1400: bool allElementsHaveSameType = true; + #####: 1401: bool foundFirstType = false; + #####: 1402: char type = 0; + -: 1403: + #####: 1404: {forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 1405: if (!e) { +branch 0 never executed +branch 1 never executed + #####: 1406: if (foundFirstType) { +branch 0 never executed +branch 1 never executed + #####: 1407: if (type != S_UNDEFINED) { +branch 0 never executed +branch 1 never executed + #####: 1408: allElementsHaveSameType = false; + #####: 1409: break; + -: 1410: } + -: 1411: } + -: 1412: else { + #####: 1413: type = S_UNDEFINED; + #####: 1414: foundFirstType = true; + -: 1415: } + -: 1416: } + -: 1417: else { + #####: 1418: if (foundFirstType) { +branch 0 never executed +branch 1 never executed + -: 1419: u8 nextType; + #####: 1420: switch(e->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed + -: 1421: case DICT: + #####: 1422: nextType = isDictUniform((sDictt*)e); +call 0 never executed + #####: 1423: break; + -: 1424: case ARRAY: + #####: 1425: nextType = isArrayUniform((sArrayt*)e); +call 0 never executed + #####: 1426: break; + -: 1427: default: + #####: 1428: nextType = NET_SERIAL_TYPES[(u8)e->type]; + -: 1429: } + #####: 1430: if (nextType != type) { +branch 0 never executed +branch 1 never executed + #####: 1431: allElementsHaveSameType = false; + #####: 1432: break; + -: 1433: } + -: 1434: } + -: 1435: else { + #####: 1436: switch(e->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed + -: 1437: case DICT: + #####: 1438: type = isDictUniform((sDictt*)e); +call 0 never executed + #####: 1439: break; + -: 1440: case ARRAY: + #####: 1441: type = isArrayUniform((sArrayt*)e); +call 0 never executed + #####: 1442: break; + -: 1443: default: + #####: 1444: type = NET_SERIAL_TYPES[(u8)e->type]; + -: 1445: } + #####: 1446: foundFirstType = true; + -: 1447: } + -: 1448: } + -: 1449: }} + -: 1450: + #####: 1451: if (allElementsHaveSameType) { +branch 0 never executed +branch 1 never executed + -: 1452: // pack array + #####: 1453: if (packed) { +branch 0 never executed +branch 1 never executed + #####: 1454: uintToNetTypeVarint(r, type, array->count); +call 0 never executed + -: 1455: } + -: 1456: else { + #####: 1457: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1458: sBytesPush(r, (type << 4) + UNIFORM_ARRAY); +call 0 never executed + #####: 1459: uintToVarint(r, array->count); +call 0 never executed + -: 1460: } + -: 1461: else { + -: 1462: // high nibble + #####: 1463: ctx->nibble = lowNbl; + #####: 1464: data = (char *)&((*r)->data) + ctx->nblOffset; + #####: 1465: *data |= UNIFORM_ARRAY << 4; + #####: 1466: uintToNetTypeVarint(r, type, array->count); +call 0 never executed + -: 1467: } + -: 1468: } + -: 1469: + #####: 1470: switch(type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed + -: 1471: case S_BOOL: + #####: 1472: {forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 1473: if (!ctx->boolOffset) { +branch 0 never executed +branch 1 never executed + -: 1474: // new packed bools + #####: 1475: storeNew8bPackedBool(e); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1476: } + -: 1477: else { + -: 1478: // there was a bool before this one, fill bits in nibbles + #####: 1479: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + -: 1480: // previous packed bool is full + -: 1481: // next byte is the new packed bools + #####: 1482: storeNew8bPackedBool(e); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1483: } + -: 1484: else { + #####: 1485: storeBool(e); +branch 0 never executed +branch 1 never executed + -: 1486: } + -: 1487: } + -: 1488: }} + #####: 1489: break; + -: 1490: case S_DICT: + -: 1491: case UNIFORM_DICT: + #####: 1492: {forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 1493: dictNetSerialLevel2(r, (sDictt *)e, ctx, /*packed=*/true); +call 0 never executed + -: 1494: }} + #####: 1495: break; + -: 1496: case S_DOUBLE: + #####: 1497: {forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 1498: sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); +call 0 never executed + -: 1499: }} + #####: 1500: break; + -: 1501: case S_INT: + #####: 1502: {forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 1503: i64 v = ((sIntt *)e)->value; + #####: 1504: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 never executed + -: 1505: }} + #####: 1506: break; + -: 1507: case S_STRING: + #####: 1508: {forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 1509: sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); +call 0 never executed + -: 1510: }} + #####: 1511: break; + -: 1512: case S_ARRAY: + -: 1513: case UNIFORM_ARRAY: + #####: 1514: {forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 1515: arrayNetSerialLevel2(r, (sArrayt *)e, ctx, /*packed=*/true); +call 0 never executed + -: 1516: }} + #####: 1517: break; + -: 1518: case S_BYTES: + #####: 1519: {forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 1520: B = (sBytest *)e; + #####: 1521: uintToVarint(r, B->count); +call 0 never executed + #####: 1522: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + -: 1523: }} + #####: 1524: break; + -: 1525: } + #####: 1526: ret; + -: 1527: } + -: 1528: + #####: 1529: if (packed) { +branch 0 never executed +branch 1 never executed + #####: 1530: uintToVarint(r, array->count); +call 0 never executed + -: 1531: } + -: 1532: else { + #####: 1533: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1534: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)array->type], array->count); +call 0 never executed + -: 1535: } + -: 1536: else { + -: 1537: // high nibble + #####: 1538: storeTypeInHighNbl(array); + #####: 1539: uintToVarint(r, array->count); +call 0 never executed + -: 1540: } + -: 1541: } + -: 1542: + #####: 1543: forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 1544: if (!e) { +branch 0 never executed +branch 1 never executed + -: 1545: // empty slots are represented as undefined elements + #####: 1546: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1547: sBytesPush(r, NET_SERIAL_TYPES[UNDEFINED]); +call 0 never executed + #####: 1548: ctx->nibble = highNbl; + #####: 1549: ctx->nblOffset = (*r)->count -1; + -: 1550: } + -: 1551: else { + -: 1552: // high nibble + #####: 1553: ctx->nibble = lowNbl; + #####: 1554: data = (char *)&((*r)->data) + ctx->nblOffset; + #####: 1555: *data |= NET_SERIAL_TYPES[UNDEFINED] << 4; + -: 1556: } + -: 1557: } + -: 1558: else { + #####: 1559: switch(e->type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 1560: case UNDEFINED: + -: 1561: case CONTAINER: + #####: 1562: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1563: storeTypeOnly(e); +call 0 never executed + -: 1564: } + -: 1565: else { + -: 1566: // high nibble + #####: 1567: storeTypeInHighNbl(e); + -: 1568: } + #####: 1569: break; + -: 1570: case BOOL: + #####: 1571: if (!ctx->boolOffset) { +branch 0 never executed +branch 1 never executed + -: 1572: // new packed bools + #####: 1573: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1574: storeNew4bPackedBool(e); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1575: } + -: 1576: else { + -: 1577: // high nibble, next byte is packed bools + #####: 1578: storeTypeInHighNbl(e); + #####: 1579: storeNew8bPackedBool(e); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1580: } + -: 1581: } + -: 1582: else { + -: 1583: // there was a bool before this one, fill bits in nibbles + #####: 1584: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1585: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + -: 1586: // previous packed bool is full + -: 1587: // this byte is the new packed bools + #####: 1588: storeNew4bPackedBool(e); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1589: } + -: 1590: else { + #####: 1591: storeTypeOnly(e); +call 0 never executed + #####: 1592: storeBool(e); +branch 0 never executed +branch 1 never executed + -: 1593: } + -: 1594: } + -: 1595: else { + -: 1596: // high nibble + #####: 1597: storeTypeInHighNbl(e); + #####: 1598: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + -: 1599: // previous packed bool is full + -: 1600: // next byte is the new packed bools + #####: 1601: storeNew8bPackedBool(e); +branch 0 never executed +branch 1 never executed +call 2 never executed + -: 1602: } + -: 1603: else { + #####: 1604: storeBool(e); +branch 0 never executed +branch 1 never executed + -: 1605: } + -: 1606: } + -: 1607: } + #####: 1608: break; + -: 1609: case DICT: + #####: 1610: dictNetSerialLevel2(r, (sDictt *)e, ctx, /*packed=*/false); +call 0 never executed + #####: 1611: break; + -: 1612: case DOUBLE: + #####: 1613: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1614: storeTypeOnly(e); +call 0 never executed + -: 1615: } + -: 1616: else { + -: 1617: // high nibble + #####: 1618: storeTypeInHighNbl(e); + -: 1619: } + #####: 1620: sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); +call 0 never executed + #####: 1621: break; + -: 1622: case INT: { + -: 1623: // encode int to varint + -: 1624: // v is int64_t to convert to varint + #####: 1625: i64 v = ((sIntt *)&(e->type))->value; + #####: 1626: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 1627: // encode v with arithmetic shifts + #####: 1628: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], (v << 1) ^ (v >> 63)); +call 0 never executed + -: 1629: } + -: 1630: else { + -: 1631: // high nibble + #####: 1632: storeTypeInHighNbl(e); + #####: 1633: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 never executed + -: 1634: } + -: 1635: } + #####: 1636: break; + -: 1637: case STRING: + #####: 1638: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1639: storeTypeOnly(e); +call 0 never executed + -: 1640: } + -: 1641: else { + -: 1642: // high nibble + #####: 1643: storeTypeInHighNbl(e); + -: 1644: } + #####: 1645: sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); +call 0 never executed + #####: 1646: break; + -: 1647: case ARRAY: + #####: 1648: arrayNetSerialLevel2(r, (sArrayt *)e, ctx, /*packed=*/false); +call 0 never executed + #####: 1649: break; + -: 1650: case BYTES: + #####: 1651: B = (sBytest *)e; + #####: 1652: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 1653: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], B->count); +call 0 never executed + -: 1654: } + -: 1655: else { + -: 1656: // high nibble + #####: 1657: storeTypeInHighNbl(e); + #####: 1658: uintToVarint(r, B->count); +call 0 never executed + -: 1659: } + #####: 1660: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + #####: 1661: break; + -: 1662: } + -: 1663: } + -: 1664: } + #####: 1665: ret; + -: 1666:} + -: 1667: +function serialNetSerialLevel2 called 0 returned 0% blocks executed 0% + #####: 1668:internal smallBytest* serialNetSerialLevel2(smallJsont *self) { + -: 1669: + #####: 1670: smallt *o = getsoG(self); +call 0 never executed + -: 1671: + #####: 1672: if (o == NULL) +branch 0 never executed +branch 1 never executed + #####: 1673: ret NULL; + -: 1674: + #####: 1675: sBytest *B = netSerialLevel2(o); +call 0 never executed + -: 1676: + #####: 1677: if (!B) { +branch 0 never executed +branch 1 never executed + #####: 1678: ret NULL; + -: 1679: } + -: 1680: + #####: 1681: createAllocateSmallBytes(r); +call 0 never executed + #####: 1682: r->B = B; + #####: 1683: ret r; + -: 1684:} + -: 1685: + -: 1686:// level 3 + -: 1687: +function netSerial called 76 returned 100% blocks executed 88% + 76: 1688:internal sBytest* netSerial(smallt *o) { + 76: 1689: sBytest *r = NULL; + 76: 1690: sBytest *B = NULL; + 76: 1691: contextt ctx = {.nibble=lowNbl, .nblOffset=0, .boolShift = 0, .boolOffset=0}; + -: 1692: + 76: 1693: switch(o->type) { +branch 0 taken 1% +branch 1 taken 1% +branch 2 taken 47% +branch 3 taken 1% +branch 4 taken 1% +branch 5 taken 1% +branch 6 taken 46% +branch 7 taken 0% +branch 8 taken 0% + -: 1694: case UNDEFINED: + -: 1695: case CONTAINER: + 1: 1696: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 returned 100% + 1: 1697: break; + -: 1698: case BOOL: { + 1: 1699: u8 c = NET_SERIAL_TYPES[(u8)o->type]; + -: 1700: // set bit 4 when true + 1: 1701: if (((sBoolt *)&(o->type))->value) +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 1: 1702: c |= (1<<4); + 1: 1703: sBytesPush(&r, c); +call 0 returned 100% + -: 1704: } + 1: 1705: break; + -: 1706: case DICT: + 36: 1707: dictNetSerial(&r, (sDictt *)&(o->type), &ctx, /*packing=*/NOPACKING); +call 0 returned 100% + 36: 1708: break; + -: 1709: case DOUBLE: + 1: 1710: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 returned 100% + 1: 1711: sBytesPushBuffer(&r, &((sDoublet *)&(o->type))->value, sizeof(double)); +call 0 returned 100% + 1: 1712: break; + -: 1713: case INT: { + -: 1714: // encode int to varint + -: 1715: // v is int64_t to convert to varint + 1: 1716: i64 v = ((sIntt *)&(o->type))->value; + -: 1717: // encode v with arithmetic shifts + 1: 1718: uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], (v << 1) ^ (v >> 63)); +call 0 returned 100% + -: 1719: } + 1: 1720: break; + -: 1721: case STRING: + 1: 1722: sBytesPush(&r, NET_SERIAL_TYPES[(u8)o->type]); +call 0 returned 100% + 1: 1723: sBytesPushBuffer(&r, &((sStringt *)&(o->type))->data, sizeof(sStringt) + strlen(&(((sStringt *)&(o->type))->data)) -1); +call 0 returned 100% + 1: 1724: break; + -: 1725: case ARRAY: + 35: 1726: arrayNetSerial(&r, (sArrayt *)&(o->type), &ctx, /*packing=*/NOPACKING); +call 0 returned 100% + 35: 1727: break; + -: 1728: case BYTES: + #####: 1729: B = (sBytest *)&(o->type); + #####: 1730: uintToNetTypeVarint(&r, NET_SERIAL_TYPES[(u8)o->type], B->count); +call 0 never executed + #####: 1731: sBytesPushBuffer(&r, &(B->data), B->count); +call 0 never executed + #####: 1732: break; + -: 1733: } + 76: 1734: ret r; + -: 1735:} + -: 1736: + -: 1737:/** + -: 1738: * serialize dictionary + -: 1739: * + -: 1740: * the serialized dict is pushed to r. + -: 1741: * All elements are serialized recursively + -: 1742: * + -: 1743: * the data in containers is not serialized + -: 1744: * + -: 1745: * \param + -: 1746: * r small bytes object + -: 1747: * dict dictionary to serialize + -: 1748: */ +function dictNetSerial called 76 returned 100% blocks executed 91% + 76: 1749:internal void dictNetSerial(sBytest **r, sDictt *dict, contextt *ctx, packingT packing) { + 76: 1750: sBytest *B = NULL; + 76: 1751: char *data = NULL; + -: 1752: + -: 1753: // check if all elements have same type + 76: 1754: bool allElementsHaveSameType = true; + 76: 1755: bool foundFirstType = false; + 76: 1756: char type = 0; + 194: 1757: {forEachSDict(dict, e) { +branch 0 taken 79% +branch 1 taken 21% (fallthrough) + 154: 1758: if (e->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 154: 1759: if (foundFirstType) { +branch 0 taken 58% (fallthrough) +branch 1 taken 42% + -: 1760: u8 nextType; + 89: 1761: switch(e->data->type) { +branch 0 taken 17% +branch 1 taken 9% +branch 2 taken 74% + -: 1762: case DICT: + 15: 1763: nextType = isDictUniform((sDictt*)e->data); +call 0 returned 100% + 15: 1764: break; + -: 1765: case ARRAY: + 8: 1766: nextType = isArrayUniform((sArrayt*)e->data); +call 0 returned 100% + 8: 1767: break; + -: 1768: default: + 66: 1769: nextType = NET_SERIAL_TYPES[(u8)e->data->type]; + -: 1770: } + 89: 1771: if (nextType != type) { +branch 0 taken 40% (fallthrough) +branch 1 taken 60% + 36: 1772: allElementsHaveSameType = false; + 36: 1773: break; + -: 1774: } + -: 1775: } + -: 1776: else { + 65: 1777: switch(e->data->type) { +branch 0 taken 8% +branch 1 taken 5% +branch 2 taken 88% + -: 1778: case DICT: + 5: 1779: type = isDictUniform((sDictt*)e->data); +call 0 returned 100% + 5: 1780: break; + -: 1781: case ARRAY: + 3: 1782: type = isArrayUniform((sArrayt*)e->data); +call 0 returned 100% + 3: 1783: break; + -: 1784: default: + 57: 1785: type = NET_SERIAL_TYPES[(u8)e->data->type]; + -: 1786: } + 65: 1787: foundFirstType = true; + -: 1788: } + -: 1789: } + -: 1790: }} + -: 1791: + 76: 1792: if (allElementsHaveSameType) { +branch 0 taken 53% (fallthrough) +branch 1 taken 47% + -: 1793: // pack dictionary + 40: 1794: if (packing == PACKED) { +branch 0 taken 45% (fallthrough) +branch 1 taken 55% + -: 1795: // uniform dict can't be packed + -: 1796: // because there is only one type of packed arrays + 18: 1797: goto normalDict; + -: 1798: } + 22: 1799: elif (packing == UNIFORM) { +branch 0 taken 18% (fallthrough) +branch 1 taken 82% + 4: 1800: uintToNetTypeVarint(r, type, dict->count); +call 0 returned 100% + -: 1801: } + -: 1802: else { + 18: 1803: if (ctx->nibble == lowNbl) { +branch 0 taken 94% (fallthrough) +branch 1 taken 6% + 17: 1804: sBytesPush(r, (type << 4) + UNIFORM_DICT); +call 0 returned 100% + 17: 1805: uintToVarint(r, dict->count); +call 0 returned 100% + -: 1806: } + -: 1807: else { + -: 1808: // high nibble + 1: 1809: ctx->nibble = lowNbl; + 1: 1810: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 1811: *data |= UNIFORM_DICT << 4; + 1: 1812: uintToNetTypeVarint(r, type, dict->count); +call 0 returned 100% + -: 1813: } + -: 1814: } + -: 1815: + 22: 1816: switch(type) { +branch 0 taken 9% +branch 1 taken 18% +branch 2 taken 9% +branch 3 taken 5% +branch 4 taken 27% +branch 5 taken 23% +branch 6 taken 9% +branch 7 taken 0% +branch 8 taken 0% + -: 1817: case S_UNDEFINED: + 8: 1818: {forEachSDict(dict, e) { +branch 0 taken 75% +branch 1 taken 25% (fallthrough) + 6: 1819: if (e->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 6: 1820: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 returned 100% + -: 1821: } + -: 1822: }} + -: 1823: + 2: 1824: break; + -: 1825: case S_BOOL: + 19: 1826: {forEachSDict(dict, e) { +branch 0 taken 79% +branch 1 taken 21% (fallthrough) + 15: 1827: if (e->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 15: 1828: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 returned 100% + -: 1829: + 15: 1830: if (!ctx->boolOffset) { +branch 0 taken 20% (fallthrough) +branch 1 taken 80% + -: 1831: // new packed bools + 3: 1832: storeNew8bPackedBool(e->data); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% +call 2 returned 100% + -: 1833: } + -: 1834: else { + -: 1835: // there was a bool before this one, fill bits in nibbles + 12: 1836: if (ctx->boolShift == 8) { +branch 0 taken 8% (fallthrough) +branch 1 taken 92% + -: 1837: // previous packed bool is full + -: 1838: // next byte is the new packed bools + 1: 1839: storeNew8bPackedBool(e->data); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% +call 2 returned 100% + -: 1840: } + -: 1841: else { + 11: 1842: storeBool(e->data); +branch 0 taken 91% (fallthrough) +branch 1 taken 9% + -: 1843: } + -: 1844: } + -: 1845: } + -: 1846: }} + 4: 1847: break; + -: 1848: case S_DICT: + -: 1849: case UNIFORM_DICT: + 6: 1850: {forEachSDict(dict, e) { +branch 0 taken 67% +branch 1 taken 33% (fallthrough) + 4: 1851: if (e->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 4: 1852: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 returned 100% + 4: 1853: dictNetSerial(r, (sDictt *)(e->data), ctx, /*packing=*/UNIFORM); +call 0 returned 100% + -: 1854: } + -: 1855: }} + 2: 1856: break; + -: 1857: case S_DOUBLE: + 4: 1858: {forEachSDict(dict, e) { +branch 0 taken 75% +branch 1 taken 25% (fallthrough) + 3: 1859: if (e->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 3: 1860: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 returned 100% + 3: 1861: sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); +call 0 returned 100% + -: 1862: } + -: 1863: }} + 1: 1864: break; + -: 1865: case S_INT: + 15: 1866: {forEachSDict(dict, e) { +branch 0 taken 60% +branch 1 taken 40% (fallthrough) + 9: 1867: if (e->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 9: 1868: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 returned 100% + 9: 1869: i64 v = ((sIntt *)(e->data))->value; + 9: 1870: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 returned 100% + -: 1871: } + -: 1872: }} + 6: 1873: break; + -: 1874: case S_STRING: + 16: 1875: {forEachSDict(dict, e) { +branch 0 taken 69% +branch 1 taken 31% (fallthrough) + 11: 1876: if (e->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 11: 1877: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 returned 100% + 11: 1878: sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); +call 0 returned 100% + -: 1879: } + -: 1880: }} + 5: 1881: break; + -: 1882: case S_ARRAY: + -: 1883: case UNIFORM_ARRAY: + 4: 1884: {forEachSDict(dict, e) { +branch 0 taken 50% +branch 1 taken 50% (fallthrough) + 2: 1885: if (e->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 2: 1886: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 returned 100% + 2: 1887: arrayNetSerial(r, (sArrayt *)(e->data), ctx, /*packing=*/UNIFORM); +call 0 returned 100% + -: 1888: } + -: 1889: }} + 2: 1890: break; + -: 1891: case S_BYTES: + #####: 1892: {forEachSDict(dict, e) { +branch 0 never executed +branch 1 never executed + #####: 1893: if (e->key) { +branch 0 never executed +branch 1 never executed + #####: 1894: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 never executed + #####: 1895: B = (sBytest *)(e->data); + #####: 1896: uintToVarint(r, B->count); +call 0 never executed + #####: 1897: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + -: 1898: } + -: 1899: }} + #####: 1900: break; + -: 1901: } + 22: 1902: ret; + -: 1903: } + -: 1904: + -: 1905: normalDict: + 54: 1906: if (packing == PACKED or packing == UNIFORM) { +branch 0 taken 57% (fallthrough) +branch 1 taken 43% +branch 2 taken 13% (fallthrough) +branch 3 taken 87% + 27: 1907: uintToVarint(r, dict->count); +call 0 returned 100% + -: 1908: } + -: 1909: else { + 27: 1910: if (ctx->nibble == lowNbl) { +branch 0 taken 93% (fallthrough) +branch 1 taken 7% + 25: 1911: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)dict->type], dict->count); +call 0 returned 100% + -: 1912: } + -: 1913: else { + -: 1914: // high nibble + -: 1915: #define storeTypeInHighNbl(o)\ + -: 1916: ctx->nibble = lowNbl;\ + -: 1917: data = (char *)&((*r)->data) + ctx->nblOffset;\ + -: 1918: *data |= NET_SERIAL_TYPES[(u8)o->type] << 4 + 2: 1919: storeTypeInHighNbl(dict); + 2: 1920: uintToVarint(r, dict->count); +call 0 returned 100% + -: 1921: } + -: 1922: } + -: 1923: + 54: 1924: bool pack = false; + -: 1925: size_t packCount; + 210: 1926: enumerateSDict(dict, e, eIdx) { +branch 0 taken 74% +branch 1 taken 26% (fallthrough) + 156: 1927: if (e->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 156: 1928: if (!pack) { +branch 0 taken 76% (fallthrough) +branch 1 taken 24% + -: 1929: // scan dict for packing + 118: 1930: if ((dict->count - eIdx) > 3) { +branch 0 taken 35% (fallthrough) +branch 1 taken 65% + -: 1931: // at least 4 elements, less than that is not worth it + 41: 1932: if ( e->data->type == DICT +branch 0 taken 93% (fallthrough) +branch 1 taken 7% + 38: 1933: or e->data->type == DOUBLE +branch 0 taken 95% (fallthrough) +branch 1 taken 5% + 36: 1934: or e->data->type == INT +branch 0 taken 94% (fallthrough) +branch 1 taken 6% + 34: 1935: or e->data->type == STRING +branch 0 taken 94% (fallthrough) +branch 1 taken 6% + 32: 1936: or e->data->type == ARRAY +branch 0 taken 94% (fallthrough) +branch 1 taken 6% + 30: 1937: or e->data->type == BYTES) { +branch 0 taken 0% (fallthrough) +branch 1 taken 100% + 11: 1938: type = e->data->type; + 11: 1939: packCount = 1; + 11: 1940: sDictElemt *element = &((dict)->elements) + eIdx; + 49: 1941: for (size_t i = eIdx+1; i < (dict)->count ; i++, element = &((dict)->elements) + i) { +branch 0 taken 100% +branch 1 taken 0% (fallthrough) + 49: 1942: if (element->key) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 49: 1943: if (element->data->type != type) { +branch 0 taken 22% (fallthrough) +branch 1 taken 78% + 11: 1944: break; + -: 1945: } + 38: 1946: packCount++; + -: 1947: } // element->key + -: 1948: } // for + 11: 1949: if (packCount > 3) { +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + 11: 1950: type = PACKED_NET_SERIAL_TYPES[(u8)type]; + 11: 1951: pack = true; + -: 1952: } + -: 1953: } // test current element type + -: 1954: } // is dict big enough + -: 1955: } // not already packing + -: 1956: + 156: 1957: sBytesPushBuffer(r, e->key, strlen(e->key) + 1); +call 0 returned 100% + -: 1958: + 156: 1959: switch(e->data->type) { +branch 0 taken 17% +branch 1 taken 20% +branch 2 taken 13% +branch 3 taken 8% +branch 4 taken 21% +branch 5 taken 14% +branch 6 taken 8% +branch 7 taken 0% +branch 8 taken 0% + -: 1960: case UNDEFINED: + -: 1961: case CONTAINER: + 26: 1962: if (ctx->nibble == lowNbl) { +branch 0 taken 92% (fallthrough) +branch 1 taken 8% + -: 1963: #define storeTypeOnly(o)\ + -: 1964: sBytesPush(r, NET_SERIAL_TYPES[(u8)o->type]);\ + -: 1965: ctx->nibble = highNbl;\ + -: 1966: ctx->nblOffset = (*r)->count -1 + 24: 1967: storeTypeOnly(e->data); +call 0 returned 100% + -: 1968: } + -: 1969: else { + 2: 1970: storeTypeInHighNbl(e->data); + -: 1971: } + 26: 1972: break; + -: 1973: case BOOL: + 31: 1974: if (!ctx->boolOffset) { +branch 0 taken 16% (fallthrough) +branch 1 taken 84% + -: 1975: // new packed bools + 5: 1976: if (ctx->nibble == lowNbl) { +branch 0 taken 60% (fallthrough) +branch 1 taken 40% + -: 1977: #define storeNew4bPackedBool(o)\ + -: 1978: u8 c = NET_SERIAL_TYPES[(u8)o->type];\ + -: 1979: /* set bit 4 when true */\ + -: 1980: if (((sBoolt *)(o))->value)\ + -: 1981: c |= (1<<4);\ + -: 1982: sBytesPush(r, c);\ + -: 1983: ctx->boolShift = 5;\ + -: 1984: ctx->boolOffset = (*r)->count -1 + 3: 1985: storeNew4bPackedBool(e->data); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% +call 2 returned 100% + -: 1986: } + -: 1987: else { + -: 1988: // high nibble, next byte is packed bools + 2: 1989: storeTypeInHighNbl(e->data); + -: 1990: #define storeNew8bPackedBool(o)\ + -: 1991: u8 c = 0;\ + -: 1992: if (((sBoolt *)(o))->value)\ + -: 1993: c = 1;\ + -: 1994: sBytesPush(r, c);\ + -: 1995: ctx->boolShift = 1;\ + -: 1996: ctx->boolOffset = (*r)->count -1 + 2: 1997: storeNew8bPackedBool(e->data); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% +call 2 returned 100% + -: 1998: } + -: 1999: } + -: 2000: else { + -: 2001: // there was a bool before this one, fill bits in nibbles + 26: 2002: if (ctx->nibble == lowNbl) { +branch 0 taken 58% (fallthrough) +branch 1 taken 42% + 15: 2003: if (ctx->boolShift == 8) { +branch 0 taken 7% (fallthrough) +branch 1 taken 93% + -: 2004: // previous packed bool is full + -: 2005: // this byte is the new packed bools + 1: 2006: storeNew4bPackedBool(e->data); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% +call 2 returned 100% + -: 2007: } + -: 2008: else { + 14: 2009: storeTypeOnly(e->data); +call 0 returned 100% + -: 2010: #define storeBool(o)\ + -: 2011: data = (char *)&((*r)->data) + ctx->boolOffset;\ + -: 2012: if (((sBoolt *)(o))->value)\ + -: 2013: *data |= 1 << ctx->boolShift;\ + -: 2014: ctx->boolShift++ + 14: 2015: storeBool(e->data); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + -: 2016: } + -: 2017: } + -: 2018: else { + -: 2019: // high nibble + 11: 2020: storeTypeInHighNbl(e->data); + 11: 2021: if (ctx->boolShift == 8) { +branch 0 taken 18% (fallthrough) +branch 1 taken 82% + -: 2022: // previous packed bool is full + -: 2023: // next byte is the new packed bools + 2: 2024: storeNew8bPackedBool(e->data); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% +call 2 returned 100% + -: 2025: } + -: 2026: else { + 9: 2027: storeBool(e->data); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + -: 2028: } + -: 2029: } + -: 2030: } + 31: 2031: break; + -: 2032: case DICT: + 20: 2033: if (pack) { +branch 0 taken 75% (fallthrough) +branch 1 taken 25% + 15: 2034: if (type) { +branch 0 taken 20% (fallthrough) +branch 1 taken 80% + -: 2035: // this is the first packed element + 3: 2036: if (ctx->nibble == lowNbl) { +branch 0 taken 67% (fallthrough) +branch 1 taken 33% + 2: 2037: uintToNetTypeVarint(r, type, packCount); +call 0 returned 100% + -: 2038: } + -: 2039: else { + -: 2040: // high nibble + -: 2041: // store type in high nibble + 1: 2042: ctx->nibble = lowNbl; + 1: 2043: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 2044: *data |= type << 4; + 1: 2045: uintToVarint(r, packCount); +call 0 returned 100% + -: 2046: } + 3: 2047: type = 0; + -: 2048: } // if type + -: 2049: + 15: 2050: dictNetSerial(r, (sDictt *)(e->data), ctx, /*packing=*/PACKED); +call 0 returned 100% + -: 2051: // stop packing when packCount == 0 + 15: 2052: packCount--; + 15: 2053: if (!packCount) pack = false; +branch 0 taken 20% (fallthrough) +branch 1 taken 80% + -: 2054: } // if pack + -: 2055: else + 5: 2056: dictNetSerial(r, (sDictt *)(e->data), ctx, /*packing=*/NOPACKING); +call 0 returned 100% + 20: 2057: break; + -: 2058: case DOUBLE: + 12: 2059: if (pack) { +branch 0 taken 83% (fallthrough) +branch 1 taken 17% + 10: 2060: if (type) { +branch 0 taken 20% (fallthrough) +branch 1 taken 80% + -: 2061: // this is the first packed element + 2: 2062: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2063: uintToNetTypeVarint(r, type, packCount); +call 0 returned 100% + -: 2064: } + -: 2065: else { + -: 2066: // high nibble + -: 2067: // store type in high nibble + 1: 2068: ctx->nibble = lowNbl; + 1: 2069: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 2070: *data |= type << 4; + 1: 2071: uintToVarint(r, packCount); +call 0 returned 100% + -: 2072: } + 2: 2073: type = 0; + -: 2074: } // if type + -: 2075: + 10: 2076: sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); +call 0 returned 100% + -: 2077: // stop packing when packCount == 0 + 10: 2078: packCount--; + 10: 2079: if (!packCount) pack = false; +branch 0 taken 20% (fallthrough) +branch 1 taken 80% + -: 2080: } // if pack + -: 2081: else { + 2: 2082: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2083: storeTypeOnly(e->data); +call 0 returned 100% + -: 2084: } + -: 2085: else { + -: 2086: // high nibble + 1: 2087: storeTypeInHighNbl(e->data); + -: 2088: } + 2: 2089: sBytesPushBuffer(r, &((sDoublet *)(e->data))->value, sizeof(double)); +call 0 returned 100% + -: 2090: } + 12: 2091: break; + -: 2092: case INT: + 32: 2093: if (pack) { +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + 8: 2094: if (type) { +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2095: // this is the first packed element + 2: 2096: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2097: uintToNetTypeVarint(r, type, packCount); +call 0 returned 100% + -: 2098: } + -: 2099: else { + -: 2100: // high nibble + -: 2101: // store type in high nibble + 1: 2102: ctx->nibble = lowNbl; + 1: 2103: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 2104: *data |= type << 4; + 1: 2105: uintToVarint(r, packCount); +call 0 returned 100% + -: 2106: } + 2: 2107: type = 0; + -: 2108: } // if type + -: 2109: + 8: 2110: i64 v = ((sIntt *)(e->data))->value; + 8: 2111: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 returned 100% + -: 2112: // stop packing when packCount == 0 + 8: 2113: packCount--; + 8: 2114: if (!packCount) pack = false; +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2115: } // if pack + -: 2116: else { + -: 2117: // encode int to varint + -: 2118: // v is int64_t to convert to varint + 24: 2119: i64 v = ((sIntt *)(e->data))->value; + 24: 2120: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + -: 2121: // encode v with arithmetic shifts + 12: 2122: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], (v << 1) ^ (v >> 63)); +call 0 returned 100% + -: 2123: } + -: 2124: else { + -: 2125: // high nibble + 12: 2126: storeTypeInHighNbl(e->data); + 12: 2127: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 returned 100% + -: 2128: } + -: 2129: } + 32: 2130: break; + -: 2131: case STRING: + 22: 2132: if (pack) { +branch 0 taken 36% (fallthrough) +branch 1 taken 64% + 8: 2133: if (type) { +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2134: // this is the first packed element + 2: 2135: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2136: uintToNetTypeVarint(r, type, packCount); +call 0 returned 100% + -: 2137: } + -: 2138: else { + -: 2139: // high nibble + -: 2140: // store type in high nibble + 1: 2141: ctx->nibble = lowNbl; + 1: 2142: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 2143: *data |= type << 4; + 1: 2144: uintToVarint(r, packCount); +call 0 returned 100% + -: 2145: } + 2: 2146: type = 0; + -: 2147: } // if type + -: 2148: + 8: 2149: sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); +call 0 returned 100% + -: 2150: // stop packing when packCount == 0 + 8: 2151: packCount--; + 8: 2152: if (!packCount) pack = false; +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2153: } // if pack + -: 2154: else { + 14: 2155: if (ctx->nibble == lowNbl) { +branch 0 taken 93% (fallthrough) +branch 1 taken 7% + 13: 2156: storeTypeOnly(e->data); +call 0 returned 100% + -: 2157: } + -: 2158: else { + -: 2159: // high nibble + 1: 2160: storeTypeInHighNbl(e->data); + -: 2161: } + 14: 2162: sBytesPushBuffer(r, &((sStringt *)(e->data))->data, sizeof(sStringt) + strlen(&(((sStringt *)(e->data))->data)) -1); +call 0 returned 100% + -: 2163: } + 22: 2164: break; + -: 2165: case ARRAY: + 13: 2166: if (pack) { +branch 0 taken 62% (fallthrough) +branch 1 taken 38% + 8: 2167: if (type) { +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2168: // this is the first packed element + 2: 2169: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2170: uintToNetTypeVarint(r, type, packCount); +call 0 returned 100% + -: 2171: } + -: 2172: else { + -: 2173: // high nibble + -: 2174: // store type in high nibble + 1: 2175: ctx->nibble = lowNbl; + 1: 2176: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 2177: *data |= type << 4; + 1: 2178: uintToVarint(r, packCount); +call 0 returned 100% + -: 2179: } + 2: 2180: type = 0; + -: 2181: } // if type + -: 2182: + 8: 2183: arrayNetSerial(r, (sArrayt *)(e->data), ctx, /*packing=*/PACKED); +call 0 returned 100% + -: 2184: // stop packing when packCount == 0 + 8: 2185: packCount--; + 8: 2186: if (!packCount) pack = false; +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2187: } // if pack + -: 2188: else + 5: 2189: arrayNetSerial(r, (sArrayt *)(e->data), ctx, /*packing=*/NOPACKING); +call 0 returned 100% + 13: 2190: break; + -: 2191: case BYTES: + #####: 2192: if (pack) { +branch 0 never executed +branch 1 never executed + #####: 2193: if (type) { +branch 0 never executed +branch 1 never executed + -: 2194: // this is the first packed element + #####: 2195: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 2196: uintToNetTypeVarint(r, type, packCount); +call 0 never executed + -: 2197: } + -: 2198: else { + -: 2199: // high nibble + -: 2200: // store type in high nibble + #####: 2201: ctx->nibble = lowNbl; + #####: 2202: data = (char *)&((*r)->data) + ctx->nblOffset; + #####: 2203: *data |= type << 4; + #####: 2204: uintToVarint(r, packCount); +call 0 never executed + -: 2205: } + #####: 2206: type = 0; + -: 2207: } // if type + -: 2208: + #####: 2209: B = (sBytest *)(e->data); + #####: 2210: uintToVarint(r, B->count); +call 0 never executed + #####: 2211: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + -: 2212: // stop packing when packCount == 0 + #####: 2213: packCount--; + #####: 2214: if (!packCount) pack = false; +branch 0 never executed +branch 1 never executed + -: 2215: } // if pack + -: 2216: else { + #####: 2217: B = (sBytest *)(e->data); + #####: 2218: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 2219: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->data->type], B->count); +call 0 never executed + -: 2220: } + -: 2221: else { + -: 2222: // high nibble + #####: 2223: storeTypeInHighNbl(e->data); + #####: 2224: uintToVarint(r, B->count); +call 0 never executed + -: 2225: } + #####: 2226: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + -: 2227: } + #####: 2228: break; + -: 2229: } + -: 2230: } + -: 2231: } + 54: 2232: ret; + -: 2233:} + -: 2234: + -: 2235:/** + -: 2236: * serialize array + -: 2237: * + -: 2238: * the serialized array is pushed to r. + -: 2239: * All elements are serialized recursively + -: 2240: * + -: 2241: * the data in containers is not serialized + -: 2242: * + -: 2243: * \param + -: 2244: * r small bytes object + -: 2245: * array to serialize + -: 2246: */ +function arrayNetSerial called 71 returned 100% blocks executed 86% + 71: 2247:internal void arrayNetSerial(sBytest **r, sArrayt *array, contextt *ctx, packingT packing) { + 71: 2248: sBytest *B = NULL; + 71: 2249: char *data = NULL; + -: 2250: + -: 2251: // check if all elements have same type + 71: 2252: bool allElementsHaveSameType = true; + 71: 2253: bool foundFirstType = false; + 71: 2254: char type = 0; + -: 2255: + 213: 2256: {forEachSArray(array, e) { +branch 0 taken 82% +branch 1 taken 18% (fallthrough) + 174: 2257: if (!e) { +branch 0 taken 0% (fallthrough) +branch 1 taken 100% + #####: 2258: if (foundFirstType) { +branch 0 never executed +branch 1 never executed + #####: 2259: if (type != S_UNDEFINED) { +branch 0 never executed +branch 1 never executed + #####: 2260: allElementsHaveSameType = false; + #####: 2261: break; + -: 2262: } + -: 2263: } + -: 2264: else { + #####: 2265: type = S_UNDEFINED; + #####: 2266: foundFirstType = true; + -: 2267: } + -: 2268: } + -: 2269: else { + 174: 2270: if (foundFirstType) { +branch 0 taken 61% (fallthrough) +branch 1 taken 39% + -: 2271: u8 nextType; + 107: 2272: switch(e->type) { +branch 0 taken 7% +branch 1 taken 10% +branch 2 taken 83% + -: 2273: case DICT: + 7: 2274: nextType = isDictUniform((sDictt*)e); +call 0 returned 100% + 7: 2275: break; + -: 2276: case ARRAY: + 11: 2277: nextType = isArrayUniform((sArrayt*)e); +call 0 returned 100% + 11: 2278: break; + -: 2279: default: + 89: 2280: nextType = NET_SERIAL_TYPES[(u8)e->type]; + -: 2281: } + 107: 2282: if (nextType != type) { +branch 0 taken 30% (fallthrough) +branch 1 taken 70% + 32: 2283: allElementsHaveSameType = false; + 32: 2284: break; + -: 2285: } + -: 2286: } + -: 2287: else { + 67: 2288: switch(e->type) { +branch 0 taken 6% +branch 1 taken 7% +branch 2 taken 87% + -: 2289: case DICT: + 4: 2290: type = isDictUniform((sDictt*)e); +call 0 returned 100% + 4: 2291: break; + -: 2292: case ARRAY: + 5: 2293: type = isArrayUniform((sArrayt*)e); +call 0 returned 100% + 5: 2294: break; + -: 2295: default: + 58: 2296: type = NET_SERIAL_TYPES[(u8)e->type]; + -: 2297: } + 67: 2298: foundFirstType = true; + -: 2299: } + -: 2300: } + -: 2301: }} + -: 2302: + 71: 2303: if (allElementsHaveSameType) { +branch 0 taken 55% (fallthrough) +branch 1 taken 45% + -: 2304: // pack array + 39: 2305: if (packing == PACKED) { +branch 0 taken 41% (fallthrough) +branch 1 taken 59% + -: 2306: // uniform array can't be packed + -: 2307: // because there is only one type of packed arrays + 16: 2308: goto normalArray; + -: 2309: } + 23: 2310: elif (packing == UNIFORM) { +branch 0 taken 9% (fallthrough) +branch 1 taken 91% + 2: 2311: uintToNetTypeVarint(r, type, array->count); +call 0 returned 100% + -: 2312: } + -: 2313: else { + 21: 2314: if (ctx->nibble == lowNbl) { +branch 0 taken 76% (fallthrough) +branch 1 taken 24% + 16: 2315: sBytesPush(r, (type << 4) + UNIFORM_ARRAY); +call 0 returned 100% + 16: 2316: uintToVarint(r, array->count); +call 0 returned 100% + -: 2317: } + -: 2318: else { + -: 2319: // high nibble + 5: 2320: ctx->nibble = lowNbl; + 5: 2321: data = (char *)&((*r)->data) + ctx->nblOffset; + 5: 2322: *data |= UNIFORM_ARRAY << 4; + 5: 2323: uintToNetTypeVarint(r, type, array->count); +call 0 returned 100% + -: 2324: } + -: 2325: } + -: 2326: + 23: 2327: switch(type) { +branch 0 taken 9% +branch 1 taken 9% +branch 2 taken 4% +branch 3 taken 48% +branch 4 taken 4% +branch 5 taken 13% +branch 6 taken 0% +branch 7 taken 13% + -: 2328: case S_BOOL: + 16: 2329: {forEachSArray(array, e) { +branch 0 taken 88% +branch 1 taken 13% (fallthrough) + 14: 2330: if (!ctx->boolOffset) { +branch 0 taken 14% (fallthrough) +branch 1 taken 86% + -: 2331: // new packed bools + 2: 2332: storeNew8bPackedBool(e); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% +call 2 returned 100% + -: 2333: } + -: 2334: else { + -: 2335: // there was a bool before this one, fill bits in nibbles + 12: 2336: if (ctx->boolShift == 8) { +branch 0 taken 8% (fallthrough) +branch 1 taken 92% + -: 2337: // previous packed bool is full + -: 2338: // next byte is the new packed bools + 1: 2339: storeNew8bPackedBool(e); +branch 0 taken 0% (fallthrough) +branch 1 taken 100% +call 2 returned 100% + -: 2340: } + -: 2341: else { + 11: 2342: storeBool(e); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% + -: 2343: } + -: 2344: } + -: 2345: }} + 2: 2346: break; + -: 2347: case S_DICT: + -: 2348: case UNIFORM_DICT: + 6: 2349: {forEachSArray(array, e) { +branch 0 taken 67% +branch 1 taken 33% (fallthrough) + 4: 2350: dictNetSerial(r, (sDictt *)e, ctx, /*packing=*/UNIFORM); +call 0 returned 100% + -: 2351: }} + 2: 2352: break; + -: 2353: case S_DOUBLE: + 4: 2354: {forEachSArray(array, e) { +branch 0 taken 75% +branch 1 taken 25% (fallthrough) + 3: 2355: sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); +call 0 returned 100% + -: 2356: }} + 1: 2357: break; + -: 2358: case S_INT: + 49: 2359: {forEachSArray(array, e) { +branch 0 taken 78% +branch 1 taken 22% (fallthrough) + 38: 2360: i64 v = ((sIntt *)e)->value; + 38: 2361: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 returned 100% + -: 2362: }} + 11: 2363: break; + -: 2364: case S_STRING: + 4: 2365: {forEachSArray(array, e) { +branch 0 taken 75% +branch 1 taken 25% (fallthrough) + 3: 2366: sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); +call 0 returned 100% + -: 2367: }} + 1: 2368: break; + -: 2369: case S_ARRAY: + -: 2370: case UNIFORM_ARRAY: + 8: 2371: {forEachSArray(array, e) { +branch 0 taken 63% +branch 1 taken 38% (fallthrough) + 5: 2372: arrayNetSerial(r, (sArrayt *)e, ctx, /*packing=*/UNIFORM); +call 0 returned 100% + -: 2373: }} + 3: 2374: break; + -: 2375: case S_BYTES: + #####: 2376: {forEachSArray(array, e) { +branch 0 never executed +branch 1 never executed + #####: 2377: B = (sBytest *)e; + #####: 2378: uintToVarint(r, B->count); +call 0 never executed + #####: 2379: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + -: 2380: }} + #####: 2381: break; + -: 2382: } + 23: 2383: ret; + -: 2384: } + -: 2385: + -: 2386: normalArray: + 48: 2387: if (packing == PACKED or packing == UNIFORM) { +branch 0 taken 67% (fallthrough) +branch 1 taken 33% +branch 2 taken 16% (fallthrough) +branch 3 taken 84% + 21: 2388: uintToVarint(r, array->count); +call 0 returned 100% + -: 2389: } + -: 2390: else { + 27: 2391: if (ctx->nibble == lowNbl) { +branch 0 taken 96% (fallthrough) +branch 1 taken 4% + 26: 2392: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)array->type], array->count); +call 0 returned 100% + -: 2393: } + -: 2394: else { + -: 2395: // high nibble + 1: 2396: storeTypeInHighNbl(array); + 1: 2397: uintToVarint(r, array->count); +call 0 returned 100% + -: 2398: } + -: 2399: } + -: 2400: + 48: 2401: bool pack = false; + -: 2402: size_t packCount; + 198: 2403: enumerateSArray(array, e, eIdx) { +branch 0 taken 76% +branch 1 taken 24% (fallthrough) + 150: 2404: if (!e) { +branch 0 taken 0% (fallthrough) +branch 1 taken 100% + -: 2405: // empty slots are represented as undefined elements + #####: 2406: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 2407: sBytesPush(r, NET_SERIAL_TYPES[UNDEFINED]); +call 0 never executed + #####: 2408: ctx->nibble = highNbl; + #####: 2409: ctx->nblOffset = (*r)->count -1; + -: 2410: } + -: 2411: else { + -: 2412: // high nibble + #####: 2413: ctx->nibble = lowNbl; + #####: 2414: data = (char *)&((*r)->data) + ctx->nblOffset; + #####: 2415: *data |= NET_SERIAL_TYPES[UNDEFINED] << 4; + -: 2416: } + -: 2417: } + -: 2418: else { + 150: 2419: if (!pack) { +branch 0 taken 80% (fallthrough) +branch 1 taken 20% + -: 2420: // scan array for packing + 120: 2421: if ((array->count - eIdx) > 3) { +branch 0 taken 33% (fallthrough) +branch 1 taken 68% + -: 2422: // at least 4 elements, less than that is not worth it + 39: 2423: if ( e->type == DICT +branch 0 taken 92% (fallthrough) +branch 1 taken 8% + 36: 2424: or e->type == DOUBLE +branch 0 taken 94% (fallthrough) +branch 1 taken 6% + 34: 2425: or e->type == INT +branch 0 taken 91% (fallthrough) +branch 1 taken 9% + 31: 2426: or e->type == STRING +branch 0 taken 94% (fallthrough) +branch 1 taken 6% + 29: 2427: or e->type == ARRAY +branch 0 taken 93% (fallthrough) +branch 1 taken 7% + 27: 2428: or e->type == BYTES) { +branch 0 taken 0% (fallthrough) +branch 1 taken 100% + 12: 2429: type = e->type; + 12: 2430: packCount = 1; + 12: 2431: smallt *element = ((smallt **) &((array)->data))[eIdx]; + 45: 2432: for (size_t i = eIdx+1; i < (array)->count ; i++, element = ((smallt **) &((array)->data))[i]) { +branch 0 taken 100% +branch 1 taken 0% (fallthrough) + 45: 2433: if (!element) { +branch 0 taken 0% (fallthrough) +branch 1 taken 100% + -: 2434: // null element are undefined + #####: 2435: break; + -: 2436: } + -: 2437: else { + 45: 2438: if (element->type != type) { +branch 0 taken 27% (fallthrough) +branch 1 taken 73% + 12: 2439: break; + -: 2440: } + 33: 2441: packCount++; + -: 2442: } // if element + -: 2443: } // for + 12: 2444: if (packCount > 3) { +branch 0 taken 83% (fallthrough) +branch 1 taken 17% + 10: 2445: type = PACKED_NET_SERIAL_TYPES[(u8)type]; + 10: 2446: pack = true; + -: 2447: } + -: 2448: } // test current element type + -: 2449: } // is array big enough + -: 2450: } // not already packing + -: 2451: + 150: 2452: switch(e->type) { +branch 0 taken 18% +branch 1 taken 23% +branch 2 taken 8% +branch 3 taken 7% +branch 4 taken 20% +branch 5 taken 14% +branch 6 taken 11% +branch 7 taken 0% +branch 8 taken 0% + -: 2453: case UNDEFINED: + -: 2454: case CONTAINER: + 27: 2455: if (ctx->nibble == lowNbl) { +branch 0 taken 93% (fallthrough) +branch 1 taken 7% + 25: 2456: storeTypeOnly(e); +call 0 returned 100% + -: 2457: } + -: 2458: else { + -: 2459: // high nibble + 2: 2460: storeTypeInHighNbl(e); + -: 2461: } + 27: 2462: break; + -: 2463: case BOOL: + 34: 2464: if (!ctx->boolOffset) { +branch 0 taken 18% (fallthrough) +branch 1 taken 82% + -: 2465: // new packed bools + 6: 2466: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 3: 2467: storeNew4bPackedBool(e); +branch 0 taken 67% (fallthrough) +branch 1 taken 33% +call 2 returned 100% + -: 2468: } + -: 2469: else { + -: 2470: // high nibble, next byte is packed bools + 3: 2471: storeTypeInHighNbl(e); + 3: 2472: storeNew8bPackedBool(e); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% +call 2 returned 100% + -: 2473: } + -: 2474: } + -: 2475: else { + -: 2476: // there was a bool before this one, fill bits in nibbles + 28: 2477: if (ctx->nibble == lowNbl) { +branch 0 taken 61% (fallthrough) +branch 1 taken 39% + 17: 2478: if (ctx->boolShift == 8) { +branch 0 taken 12% (fallthrough) +branch 1 taken 88% + -: 2479: // previous packed bool is full + -: 2480: // this byte is the new packed bools + 2: 2481: storeNew4bPackedBool(e); +branch 0 taken 50% (fallthrough) +branch 1 taken 50% +call 2 returned 100% + -: 2482: } + -: 2483: else { + 15: 2484: storeTypeOnly(e); +call 0 returned 100% + 15: 2485: storeBool(e); +branch 0 taken 53% (fallthrough) +branch 1 taken 47% + -: 2486: } + -: 2487: } + -: 2488: else { + -: 2489: // high nibble + 11: 2490: storeTypeInHighNbl(e); + 11: 2491: if (ctx->boolShift == 8) { +branch 0 taken 18% (fallthrough) +branch 1 taken 82% + -: 2492: // previous packed bool is full + -: 2493: // next byte is the new packed bools + 2: 2494: storeNew8bPackedBool(e); +branch 0 taken 100% (fallthrough) +branch 1 taken 0% +call 2 returned 100% + -: 2495: } + -: 2496: else { + 9: 2497: storeBool(e); +branch 0 taken 78% (fallthrough) +branch 1 taken 22% + -: 2498: } + -: 2499: } + -: 2500: } + 34: 2501: break; + -: 2502: case DICT: + 12: 2503: if (pack) { +branch 0 taken 67% (fallthrough) +branch 1 taken 33% + 8: 2504: if (type) { +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2505: // this is the first packed element + 2: 2506: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2507: uintToNetTypeVarint(r, type, packCount); +call 0 returned 100% + -: 2508: } + -: 2509: else { + -: 2510: // high nibble + -: 2511: // store type in high nibble + 1: 2512: ctx->nibble = lowNbl; + 1: 2513: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 2514: *data |= type << 4; + 1: 2515: uintToVarint(r, packCount); +call 0 returned 100% + -: 2516: } + 2: 2517: type = 0; + -: 2518: } // if type + -: 2519: + 8: 2520: dictNetSerial(r, (sDictt *)e, ctx, /*packing=*/PACKED); +call 0 returned 100% + -: 2521: // stop packing when packCount == 0 + 8: 2522: packCount--; + 8: 2523: if (!packCount) pack = false; +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2524: } // if pack + -: 2525: else + 4: 2526: dictNetSerial(r, (sDictt *)e, ctx, /*packing=*/NOPACKING); +call 0 returned 100% + 12: 2527: break; + -: 2528: case DOUBLE: + 10: 2529: if (pack) { +branch 0 taken 80% (fallthrough) +branch 1 taken 20% + 8: 2530: if (type) { +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2531: // this is the first packed element + 2: 2532: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2533: uintToNetTypeVarint(r, type, packCount); +call 0 returned 100% + -: 2534: } + -: 2535: else { + -: 2536: // high nibble + -: 2537: // store type in high nibble + 1: 2538: ctx->nibble = lowNbl; + 1: 2539: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 2540: *data |= type << 4; + 1: 2541: uintToVarint(r, packCount); +call 0 returned 100% + -: 2542: } + 2: 2543: type = 0; + -: 2544: } // if type + -: 2545: + 8: 2546: sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); +call 0 returned 100% + -: 2547: // stop packing when packCount == 0 + 8: 2548: packCount--; + 8: 2549: if (!packCount) pack = false; +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2550: } // if pack + -: 2551: else { + 2: 2552: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2553: storeTypeOnly(e); +call 0 returned 100% + -: 2554: } + -: 2555: else { + -: 2556: // high nibble + 1: 2557: storeTypeInHighNbl(e); + -: 2558: } + 2: 2559: sBytesPushBuffer(r, &((sDoublet *)e)->value, sizeof(double)); +call 0 returned 100% + -: 2560: } + 10: 2561: break; + -: 2562: case INT: + 30: 2563: if (pack) { +branch 0 taken 27% (fallthrough) +branch 1 taken 73% + 8: 2564: if (type) { +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2565: // this is the first packed element + 2: 2566: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2567: uintToNetTypeVarint(r, type, packCount); +call 0 returned 100% + -: 2568: } + -: 2569: else { + -: 2570: // high nibble + -: 2571: // store type in high nibble + 1: 2572: ctx->nibble = lowNbl; + 1: 2573: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 2574: *data |= type << 4; + 1: 2575: uintToVarint(r, packCount); +call 0 returned 100% + -: 2576: } + 2: 2577: type = 0; + -: 2578: } // if type + -: 2579: + 8: 2580: i64 v = ((sIntt *)&(e->type))->value; + 8: 2581: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 returned 100% + -: 2582: // stop packing when packCount == 0 + 8: 2583: packCount--; + 8: 2584: if (!packCount) pack = false; +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2585: } // if pack + -: 2586: else { + -: 2587: // encode int to varint + -: 2588: // v is int64_t to convert to varint + 22: 2589: i64 v = ((sIntt *)&(e->type))->value; + 22: 2590: if (ctx->nibble == lowNbl) { +branch 0 taken 82% (fallthrough) +branch 1 taken 18% + -: 2591: // encode v with arithmetic shifts + 18: 2592: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], (v << 1) ^ (v >> 63)); +call 0 returned 100% + -: 2593: } + -: 2594: else { + -: 2595: // high nibble + 4: 2596: storeTypeInHighNbl(e); + 4: 2597: uintToVarint(r, (v << 1) ^ (v >> 63)); +call 0 returned 100% + -: 2598: } + -: 2599: } + 30: 2600: break; + -: 2601: case STRING: + 21: 2602: if (pack) { +branch 0 taken 38% (fallthrough) +branch 1 taken 62% + 8: 2603: if (type) { +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2604: // this is the first packed element + 2: 2605: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2606: uintToNetTypeVarint(r, type, packCount); +call 0 returned 100% + -: 2607: } + -: 2608: else { + -: 2609: // high nibble + -: 2610: // store type in high nibble + 1: 2611: ctx->nibble = lowNbl; + 1: 2612: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 2613: *data |= type << 4; + 1: 2614: uintToVarint(r, packCount); +call 0 returned 100% + -: 2615: } + 2: 2616: type = 0; + -: 2617: } // if type + -: 2618: + 8: 2619: sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); +call 0 returned 100% + -: 2620: // stop packing when packCount == 0 + 8: 2621: packCount--; + 8: 2622: if (!packCount) pack = false; +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2623: } // if pack + -: 2624: else { + 13: 2625: if (ctx->nibble == lowNbl) { +branch 0 taken 69% (fallthrough) +branch 1 taken 31% + 9: 2626: storeTypeOnly(e); +call 0 returned 100% + -: 2627: } + -: 2628: else { + -: 2629: // high nibble + 4: 2630: storeTypeInHighNbl(e); + -: 2631: } + 13: 2632: sBytesPushBuffer(r, &((sStringt *)e)->data, sizeof(sStringt) + strlen(&(((sStringt *)e)->data)) -1); +call 0 returned 100% + -: 2633: } + 21: 2634: break; + -: 2635: case ARRAY: + 16: 2636: if (pack) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 8: 2637: if (type) { +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2638: // this is the first packed element + 2: 2639: if (ctx->nibble == lowNbl) { +branch 0 taken 50% (fallthrough) +branch 1 taken 50% + 1: 2640: uintToNetTypeVarint(r, type, packCount); +call 0 returned 100% + -: 2641: } + -: 2642: else { + -: 2643: // high nibble + -: 2644: // store type in high nibble + 1: 2645: ctx->nibble = lowNbl; + 1: 2646: data = (char *)&((*r)->data) + ctx->nblOffset; + 1: 2647: *data |= type << 4; + 1: 2648: uintToVarint(r, packCount); +call 0 returned 100% + -: 2649: } + 2: 2650: type = 0; + -: 2651: } // if type + -: 2652: + 8: 2653: arrayNetSerial(r, (sArrayt *)e, ctx, /*packing=*/PACKED); +call 0 returned 100% + -: 2654: // stop packing when packCount == 0 + 8: 2655: packCount--; + 8: 2656: if (!packCount) pack = false; +branch 0 taken 25% (fallthrough) +branch 1 taken 75% + -: 2657: } // if pack + -: 2658: else + 8: 2659: arrayNetSerial(r, (sArrayt *)e, ctx, /*packing=*/NOPACKING); +call 0 returned 100% + 16: 2660: break; + -: 2661: case BYTES: + #####: 2662: if (pack) { +branch 0 never executed +branch 1 never executed + #####: 2663: if (type) { +branch 0 never executed +branch 1 never executed + -: 2664: // this is the first packed element + #####: 2665: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 2666: uintToNetTypeVarint(r, type, packCount); +call 0 never executed + -: 2667: } + -: 2668: else { + -: 2669: // high nibble + -: 2670: // store type in high nibble + #####: 2671: ctx->nibble = lowNbl; + #####: 2672: data = (char *)&((*r)->data) + ctx->nblOffset; + #####: 2673: *data |= type << 4; + #####: 2674: uintToVarint(r, packCount); +call 0 never executed + -: 2675: } + #####: 2676: type = 0; + -: 2677: } // if type + -: 2678: + #####: 2679: B = (sBytest *)e; + #####: 2680: uintToVarint(r, B->count); +call 0 never executed + #####: 2681: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + -: 2682: // stop packing when packCount == 0 + #####: 2683: packCount--; + #####: 2684: if (!packCount) pack = false; +branch 0 never executed +branch 1 never executed + -: 2685: } // if pack + -: 2686: else { + #####: 2687: B = (sBytest *)e; + #####: 2688: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 2689: uintToNetTypeVarint(r, NET_SERIAL_TYPES[(u8)e->type], B->count); +call 0 never executed + -: 2690: } + -: 2691: else { + -: 2692: // high nibble + #####: 2693: storeTypeInHighNbl(e); + #####: 2694: uintToVarint(r, B->count); +call 0 never executed + -: 2695: } + #####: 2696: sBytesPushBuffer(r, &(B->data), B->count); +call 0 never executed + -: 2697: } + #####: 2698: break; + -: 2699: } + -: 2700: } + -: 2701: } + 48: 2702: ret; + -: 2703:} + -: 2704: +function serialNetSerial called 76 returned 100% blocks executed 80% + 76: 2705:internal smallBytest* serialNetSerial(smallJsont *self) { + -: 2706: + 76: 2707: smallt *o = getsoG(self); +call 0 returned 100% + -: 2708: + 76: 2709: if (o == NULL) +branch 0 taken 0% (fallthrough) +branch 1 taken 100% + #####: 2710: ret NULL; + -: 2711: + 76: 2712: sBytest *B = netSerial(o); +call 0 returned 100% + -: 2713: + 76: 2714: if (!B) { +branch 0 taken 0% (fallthrough) +branch 1 taken 100% + #####: 2715: ret NULL; + -: 2716: } + -: 2717: + 76: 2718: createAllocateSmallBytes(r); +call 0 returned 100% + 76: 2719: r->B = B; + 76: 2720: ret r; + -: 2721:} + -: 2722: + -: 2723:// ------------------------------------- + -: 2724:// Deserializers + -: 2725: +function netDeserialLevel0 called 0 returned 0% blocks executed 0% + #####: 2726:internal smallt* netDeserialLevel0(sBytest *obj) { + #####: 2727: smallt *r = NULL; + #####: 2728: double *D = NULL; + #####: 2729: char *s = NULL; + #####: 2730: sBytest *B = NULL; + -: 2731: uint32_t count; + #####: 2732: char *data = NULL; + -: 2733: + #####: 2734: switch(obj->data & 0xF) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 2735: case S_UNDEFINED: + #####: 2736: r = (smallt *) allocSUndefined(); +call 0 never executed + #####: 2737: break; + -: 2738: case S_BOOL: + #####: 2739: r = (smallt *) allocSBool(obj->data & 0x10); +call 0 never executed + #####: 2740: break; + -: 2741: case S_DICT: + #####: 2742: data = (char *)&(obj->data); + #####: 2743: dictNetDeserialLevel0((sDictt **)&r, &data); +call 0 never executed + #####: 2744: break; + -: 2745: case S_DOUBLE: + #####: 2746: data = &(obj->data)+1; + #####: 2747: D = (double *)data; + #####: 2748: r = (smallt *) allocSDouble(*D); +call 0 never executed + #####: 2749: break; + -: 2750: case S_INT: + #####: 2751: data = &(obj->data); + #####: 2752: i64 v = netTypeVarintToUint((u8**)&data); +call 0 never executed + #####: 2753: v = (v >> 1) ^ ((v << 63) >> 63); + #####: 2754: r = (smallt *) allocSInt(v); +call 0 never executed + #####: 2755: break; + -: 2756: case S_STRING: + #####: 2757: s = (char *)&(obj->data)+1; + #####: 2758: r = (smallt *) allocSStringTiny(s); +call 0 never executed + #####: 2759: break; + -: 2760: case S_ARRAY: + #####: 2761: data = (char *)&(obj->data); + #####: 2762: arrayNetDeserialLevel0((sArrayt **)&r, &data); +call 0 never executed + #####: 2763: break; + -: 2764: case S_BYTES: + #####: 2765: B = allocSBytes(); +call 0 never executed + #####: 2766: data = &(obj->data); + #####: 2767: count = netTypeVarintToUint((u8**)&data); +call 0 never executed + #####: 2768: sBytesPushBuffer(&B, data, count); +call 0 never executed + #####: 2769: r = (smallt *)B; + #####: 2770: break; + -: 2771: } + -: 2772: + #####: 2773: ret r; + -: 2774:} + -: 2775: + -: 2776:/** + -: 2777: * deserialize dictionary from data + -: 2778: * + -: 2779: * a new dictionary is allocated + -: 2780: * + -: 2781: * \param + -: 2782: * dict dictionary holding the elements + -: 2783: * data serialized dictionary + -: 2784: */ +function dictNetDeserialLevel0 called 0 returned 0% blocks executed 0% + #####: 2785:internal void dictNetDeserialLevel0(sDictt **dict, char **data) { + #####: 2786: sUndefinedt *u = NULL; + #####: 2787: sBoolt *bo = NULL; + #####: 2788: double *D = NULL; + #####: 2789: sDoublet *Do = NULL; + #####: 2790: sDictt *d = NULL; + #####: 2791: sIntt *io = NULL; + #####: 2792: char *s = NULL; + #####: 2793: sStringt *so = NULL; + #####: 2794: sArrayt *a = NULL; + #####: 2795: sBytest *B = NULL; + -: 2796: uint32_t count; + -: 2797: uint32_t dictCount; + -: 2798: + #####: 2799: dictCount = netTypeVarintToUint((u8**)data); +call 0 never executed + -: 2800: + #####: 2801: if (!dictCount) { +branch 0 never executed +branch 1 never executed + #####: 2802: *dict = allocSDict(); +call 0 never executed + #####: 2803: ret; + -: 2804: } + -: 2805: + #####: 2806: loop(dictCount) { +branch 0 never executed +branch 1 never executed + -: 2807: char type; + -: 2808: char *key; + #####: 2809: key = *data; + #####: 2810: *data += strlen(key)+1; + #####: 2811: type = **data; + -: 2812: + #####: 2813: switch(type & 0xF) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 2814: case S_UNDEFINED: + #####: 2815: (*data)++; + #####: 2816: u = allocSUndefined(); +call 0 never executed + #####: 2817: sDictPushTiny(dict, key, (smallt *) u); +call 0 never executed + #####: 2818: break; + -: 2819: case S_BOOL: + #####: 2820: (*data)++; + #####: 2821: bo = allocSBool(type & 0x10); +call 0 never executed + #####: 2822: sDictPushTiny(dict, key, (smallt *) bo); +call 0 never executed + #####: 2823: break; + -: 2824: case S_DICT: + #####: 2825: d = NULL; + #####: 2826: dictNetDeserialLevel0(&d, data); +call 0 never executed + #####: 2827: sDictPushTiny(dict, key, (smallt *) d); +call 0 never executed + #####: 2828: break; + -: 2829: case S_DOUBLE: + #####: 2830: (*data)++; + #####: 2831: D = (double *)(*data); + #####: 2832: *data += sizeof(double); + #####: 2833: Do = allocSDouble(*D); +call 0 never executed + #####: 2834: sDictPushTiny(dict, key, (smallt *) Do); +call 0 never executed + #####: 2835: break; + -: 2836: case S_INT: { + #####: 2837: i64 v = netTypeVarintToUint((u8**)data); +call 0 never executed + #####: 2838: v = (v >> 1) ^ ((v << 63) >> 63); + #####: 2839: io = allocSInt(v); +call 0 never executed + #####: 2840: sDictPushTiny(dict, key, (smallt *) io); +call 0 never executed + -: 2841: } + #####: 2842: break; + -: 2843: case S_STRING: + #####: 2844: (*data)++; + #####: 2845: s = (char *)(*data); + #####: 2846: *data += strlen(s)+1; + #####: 2847: so = allocSStringTiny(s); +call 0 never executed + #####: 2848: sDictPushTiny(dict, key, (smallt *) so); +call 0 never executed + #####: 2849: break; + -: 2850: case S_ARRAY: + #####: 2851: a = NULL; + #####: 2852: arrayNetDeserialLevel0(&a, data); +call 0 never executed + #####: 2853: sDictPushTiny(dict, key, (smallt *) a); +call 0 never executed + #####: 2854: break; + -: 2855: case S_BYTES: + #####: 2856: B = allocSBytes(); +call 0 never executed + #####: 2857: count = netTypeVarintToUint((u8**)data); +call 0 never executed + #####: 2858: sBytesPushBuffer(&B, data, count); +call 0 never executed + #####: 2859: *data += count; + #####: 2860: sDictPushTiny(dict, key, (smallt *) B); +call 0 never executed + #####: 2861: break; + -: 2862: } + -: 2863: } + -: 2864:} + -: 2865: + -: 2866:/** + -: 2867: * deserialize array from data + -: 2868: * + -: 2869: * a new array is allocated + -: 2870: * + -: 2871: * \param + -: 2872: * array holding the elements + -: 2873: * data serialized dictionary + -: 2874: */ +function arrayNetDeserialLevel0 called 0 returned 0% blocks executed 0% + #####: 2875:internal void arrayNetDeserialLevel0(sArrayt **array, char **data) { + #####: 2876: sUndefinedt *u = NULL; + #####: 2877: sBoolt *bo = NULL; + #####: 2878: double *D = NULL; + #####: 2879: sDoublet *Do = NULL; + #####: 2880: sDictt *d = NULL; + #####: 2881: sIntt *io = NULL; + #####: 2882: char *s = NULL; + #####: 2883: sStringt *so = NULL; + #####: 2884: sArrayt *a = NULL; + #####: 2885: sBytest *B = NULL; + -: 2886: uint32_t count; + -: 2887: uint32_t arrayCount; + -: 2888: + #####: 2889: arrayCount = netTypeVarintToUint((u8**)data); +call 0 never executed + -: 2890: + #####: 2891: if (!arrayCount) { +branch 0 never executed +branch 1 never executed + #####: 2892: *array = allocSArray();; +call 0 never executed + #####: 2893: ret; + -: 2894: } + -: 2895: + #####: 2896: loop(arrayCount) { +branch 0 never executed +branch 1 never executed + -: 2897: char type; + #####: 2898: type = **data; + -: 2899: + #####: 2900: switch(type & 0xF) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 2901: case S_UNDEFINED: + #####: 2902: (*data)++; + #####: 2903: u = allocSUndefined(); +call 0 never executed + #####: 2904: sArrayPushTiny(array, (smallt *) u); +call 0 never executed + #####: 2905: break; + -: 2906: case S_BOOL: + #####: 2907: (*data)++; + #####: 2908: bo = allocSBool(type & 0x10); +call 0 never executed + #####: 2909: sArrayPushTiny(array, (smallt *) bo); +call 0 never executed + #####: 2910: break; + -: 2911: case S_DICT: + #####: 2912: d = NULL; + #####: 2913: dictNetDeserialLevel0(&d, data); +call 0 never executed + #####: 2914: sArrayPushTiny(array, (smallt *) d); +call 0 never executed + #####: 2915: break; + -: 2916: case S_DOUBLE: + #####: 2917: (*data)++; + #####: 2918: D = (double *)(*data); + #####: 2919: *data += sizeof(double); + #####: 2920: Do = allocSDouble(*D); +call 0 never executed + #####: 2921: sArrayPushTiny(array, (smallt *) Do); +call 0 never executed + #####: 2922: break; + -: 2923: case S_INT: { + #####: 2924: i64 v = netTypeVarintToUint((u8**)data); +call 0 never executed + #####: 2925: v = (v >> 1) ^ ((v << 63) >> 63); + #####: 2926: io = allocSInt(v); +call 0 never executed + #####: 2927: sArrayPushTiny(array, (smallt *) io); +call 0 never executed + -: 2928: } + #####: 2929: break; + -: 2930: case S_STRING: + #####: 2931: (*data)++; + #####: 2932: s = (char *)(*data); + #####: 2933: *data += strlen(s)+1; + #####: 2934: so = allocSStringTiny(s); +call 0 never executed + #####: 2935: sArrayPushTiny(array, (smallt *) so); +call 0 never executed + #####: 2936: break; + -: 2937: case S_ARRAY: + #####: 2938: a = NULL; + #####: 2939: arrayNetDeserialLevel0(&a, data); +call 0 never executed + #####: 2940: sArrayPushTiny(array, (smallt *) a); +call 0 never executed + #####: 2941: break; + -: 2942: case S_BYTES: + #####: 2943: B = allocSBytes(); +call 0 never executed + #####: 2944: count = netTypeVarintToUint((u8**)data); +call 0 never executed + #####: 2945: sBytesPushBuffer(&B, data, count); +call 0 never executed + #####: 2946: *data += count; + #####: 2947: sArrayPushTiny(array, (smallt *) B); +call 0 never executed + #####: 2948: break; + -: 2949: } + -: 2950: } + -: 2951:} + -: 2952: +function deserialNetSerialLevel0 called 0 returned 0% blocks executed 0% + #####: 2953:internal smallJsont* deserialNetSerialLevel0(smallJsont *self, smallBytest *data) { + -: 2954: + #####: 2955: if (!data) { +branch 0 never executed +branch 1 never executed + #####: 2956: ret self; + -: 2957: } + -: 2958: + #####: 2959: smallt *o = netDeserialLevel0(data->B); +call 0 never executed + -: 2960: + #####: 2961: if (!o) { +branch 0 never executed +branch 1 never executed + #####: 2962: ret self; + -: 2963: } + -: 2964: + #####: 2965: freeG(self); +call 0 never executed + -: 2966: + #####: 2967: setsoG(self, o); +call 0 never executed + -: 2968: + #####: 2969: ret self; + -: 2970:} + -: 2971: + -: 2972:// level 1 + -: 2973: +function netDeserialLevel1 called 0 returned 0% blocks executed 0% + #####: 2974:internal smallt* netDeserialLevel1(sBytest *obj) { + #####: 2975: smallt *r = NULL; + #####: 2976: double *D = NULL; + #####: 2977: char *s = NULL; + #####: 2978: sBytest *B = NULL; + -: 2979: uint32_t count; + #####: 2980: char *data = NULL; + #####: 2981: contextt ctx = {.nibble=lowNbl, .nblAddr=NULL, .boolShift = 0, .boolAddr=NULL}; + -: 2982: + #####: 2983: switch(obj->data & 0xF) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 2984: case S_UNDEFINED: + #####: 2985: r = (smallt *) allocSUndefined(); +call 0 never executed + #####: 2986: break; + -: 2987: case S_BOOL: + #####: 2988: r = (smallt *) allocSBool(obj->data & 0x10); +call 0 never executed + #####: 2989: break; + -: 2990: case S_DICT: + #####: 2991: data = (char *)&(obj->data); + -: 2992: //debug - ctx.dbuf = (u8*) data; + #####: 2993: dictNetDeserialLevel1((sDictt **)&r, (u8**)&data, &ctx); +call 0 never executed + #####: 2994: break; + -: 2995: case S_DOUBLE: + #####: 2996: data = &(obj->data)+1; + #####: 2997: D = (double *)data; + #####: 2998: r = (smallt *) allocSDouble(*D); +call 0 never executed + #####: 2999: break; + -: 3000: case S_INT: + #####: 3001: data = &(obj->data); + #####: 3002: i64 v = netTypeVarintToUint((u8**)&data); +call 0 never executed + #####: 3003: v = (v >> 1) ^ ((v << 63) >> 63); + #####: 3004: r = (smallt *) allocSInt(v); +call 0 never executed + #####: 3005: break; + -: 3006: case S_STRING: + #####: 3007: s = (char *)&(obj->data)+1; + #####: 3008: r = (smallt *) allocSStringTiny(s); +call 0 never executed + #####: 3009: break; + -: 3010: case S_ARRAY: + #####: 3011: data = (char *)&(obj->data); + -: 3012: //debug - ctx.dbuf = (u8*) data; + #####: 3013: arrayNetDeserialLevel1((sArrayt **)&r, (u8**)&data, &ctx); +call 0 never executed + #####: 3014: break; + -: 3015: case S_BYTES: + #####: 3016: B = allocSBytes(); +call 0 never executed + #####: 3017: data = &(obj->data); + #####: 3018: count = netTypeVarintToUint((u8**)&data); +call 0 never executed + #####: 3019: sBytesPushBuffer(&B, data, count); +call 0 never executed + #####: 3020: r = (smallt *)B; + #####: 3021: break; + -: 3022: } + -: 3023: + #####: 3024: ret r; + -: 3025:} + -: 3026: + -: 3027:/** + -: 3028: * deserialize dictionary from data + -: 3029: * + -: 3030: * a new dictionary is allocated + -: 3031: * + -: 3032: * \param + -: 3033: * dict dictionary holding the elements + -: 3034: * data serialized dictionary + -: 3035: */ +function dictNetDeserialLevel1 called 0 returned 0% blocks executed 0% + #####: 3036:internal void dictNetDeserialLevel1(sDictt **dict, u8 **data, contextt *ctx) { + #####: 3037: sUndefinedt *u = NULL; + #####: 3038: sBoolt *bo = NULL; + #####: 3039: double *D = NULL; + #####: 3040: sDoublet *Do = NULL; + #####: 3041: sDictt *d = NULL; + #####: 3042: sIntt *io = NULL; + #####: 3043: char *s = NULL; + #####: 3044: sStringt *so = NULL; + #####: 3045: sArrayt *a = NULL; + #####: 3046: sBytest *B = NULL; + -: 3047: uint32_t count; + -: 3048: uint32_t dictCount; + -: 3049: + #####: 3050: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3051: dictCount = netTypeVarintToUint(data); +call 0 never executed + -: 3052: } + -: 3053: else { + -: 3054: // high nibble + -: 3055: // type = *(ctx->dbuf + ctx->nblOffset) >> 4; + -: 3056: #define readTypeInHighNbl\ + -: 3057: ctx->nibble = lowNbl;\ + -: 3058: if (ctx->nblAddr == *data)\ + -: 3059: /* data points to the type, next byte is count */\ + -: 3060: (*data)++ + #####: 3061: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3062: dictCount = varintToUint(data); +call 0 never executed + -: 3063: } + -: 3064: + #####: 3065: if (!dictCount) { +branch 0 never executed +branch 1 never executed + #####: 3066: *dict = allocSDict(); +call 0 never executed + #####: 3067: ret; + -: 3068: } + -: 3069: + #####: 3070: loop(dictCount) { +branch 0 never executed +branch 1 never executed + #####: 3071: char *key = (char*)*data; + #####: 3072: *data += strlen(key)+1; + -: 3073: char type; + #####: 3074: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3075: type = (**data) & 0xF; + -: 3076: } + -: 3077: else { + -: 3078: // high nibble + #####: 3079: type = (*ctx->nblAddr) >> 4; + -: 3080: } + -: 3081: + #####: 3082: switch(type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 3083: case S_UNDEFINED: + #####: 3084: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 3085: #define readTypeOnly\ + -: 3086: ctx->nibble = highNbl;\ + -: 3087: ctx->nblAddr = *data;\ + -: 3088: (*data)++ + #####: 3089: readTypeOnly; + -: 3090: } + -: 3091: else { + -: 3092: // high nibble + #####: 3093: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3094: } + #####: 3095: u = allocSUndefined(); +call 0 never executed + #####: 3096: sDictPushTiny(dict, key, (smallt *) u); +call 0 never executed + #####: 3097: break; + -: 3098: case S_BOOL: + #####: 3099: if (!ctx->boolAddr) { +branch 0 never executed +branch 1 never executed + -: 3100: // new packed bools + #####: 3101: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 3102: #define read4bPackedBool\ + -: 3103: ctx->boolShift = 5;\ + -: 3104: ctx->boolAddr = *data;\ + -: 3105: (*data)++ + #####: 3106: read4bPackedBool; + #####: 3107: bo = allocSBool((*ctx->boolAddr) & 0x10); +call 0 never executed + -: 3108: } + -: 3109: else { + -: 3110: // high nibble + #####: 3111: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3112: #define read8bPackedBool\ + -: 3113: ctx->boolShift = 1;\ + -: 3114: ctx->boolAddr = *data;\ + -: 3115: (*data)++ + #####: 3116: read8bPackedBool; + #####: 3117: bo = allocSBool((*ctx->boolAddr) & 0x1); +call 0 never executed + -: 3118: } + -: 3119: } + -: 3120: else { + -: 3121: // there was a bool before this one, read bits in nibbles + #####: 3122: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3123: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + #####: 3124: read4bPackedBool; + #####: 3125: bo = allocSBool((*ctx->boolAddr) & 0x10); +call 0 never executed + -: 3126: } + -: 3127: else { + #####: 3128: readTypeOnly; + #####: 3129: bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); +call 0 never executed + -: 3130: } + -: 3131: } + -: 3132: else { + -: 3133: // high nibble + #####: 3134: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3135: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + #####: 3136: read8bPackedBool; + #####: 3137: bo = allocSBool((*ctx->boolAddr) & 0x1); +call 0 never executed + -: 3138: } + -: 3139: else { + -: 3140: // high nibble + #####: 3141: bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); +call 0 never executed + -: 3142: } + -: 3143: } + -: 3144: } + #####: 3145: sDictPushTiny(dict, key, (smallt *) bo); +call 0 never executed + #####: 3146: break; + -: 3147: case S_DICT: + #####: 3148: d = NULL; + #####: 3149: dictNetDeserialLevel1(&d, data, ctx); +call 0 never executed + #####: 3150: sDictPushTiny(dict, key, (smallt *) d); +call 0 never executed + #####: 3151: break; + -: 3152: case S_DOUBLE: + #####: 3153: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3154: readTypeOnly; + -: 3155: } + -: 3156: else { + -: 3157: // high nibble + #####: 3158: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3159: } + #####: 3160: D = (double *)(*data); + #####: 3161: *data += sizeof(double); + #####: 3162: Do = allocSDouble(*D); +call 0 never executed + #####: 3163: sDictPushTiny(dict, key, (smallt *) Do); +call 0 never executed + #####: 3164: break; + -: 3165: case S_INT: { + -: 3166: i64 v; + #####: 3167: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3168: v = netTypeVarintToUint((u8**)data); +call 0 never executed + -: 3169: } + -: 3170: else { + -: 3171: // high nibble + #####: 3172: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3173: v = varintToUint(data); +call 0 never executed + -: 3174: } + #####: 3175: v = (v >> 1) ^ ((v << 63) >> 63); + #####: 3176: io = allocSInt(v); +call 0 never executed + #####: 3177: sDictPushTiny(dict, key, (smallt *) io); +call 0 never executed + -: 3178: } + #####: 3179: break; + -: 3180: case S_STRING: + #####: 3181: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3182: readTypeOnly; + -: 3183: } + -: 3184: else { + -: 3185: // high nibble + #####: 3186: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3187: } + #####: 3188: s = (char *)(*data); + #####: 3189: *data += strlen(s)+1; + #####: 3190: so = allocSStringTiny(s); +call 0 never executed + #####: 3191: sDictPushTiny(dict, key, (smallt *) so); +call 0 never executed + #####: 3192: break; + -: 3193: case S_ARRAY: + #####: 3194: a = NULL; + #####: 3195: arrayNetDeserialLevel1(&a, data, ctx); +call 0 never executed + #####: 3196: sDictPushTiny(dict, key, (smallt *) a); +call 0 never executed + #####: 3197: break; + -: 3198: case S_BYTES: + #####: 3199: B = allocSBytes(); +call 0 never executed + #####: 3200: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3201: count = netTypeVarintToUint((u8**)data); +call 0 never executed + -: 3202: } + -: 3203: else { + -: 3204: // high nibble + #####: 3205: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3206: count = varintToUint((u8**)data); +call 0 never executed + -: 3207: } + #####: 3208: sBytesPushBuffer(&B, data, count); +call 0 never executed + #####: 3209: *data += count; + #####: 3210: sDictPushTiny(dict, key, (smallt *) B); +call 0 never executed + #####: 3211: break; + -: 3212: } + -: 3213: } + -: 3214:} + -: 3215: + -: 3216:/** + -: 3217: * deserialize array from data + -: 3218: * + -: 3219: * a new array is allocated + -: 3220: * + -: 3221: * \param + -: 3222: * array holding the elements + -: 3223: * data serialized dictionary + -: 3224: */ +function arrayNetDeserialLevel1 called 0 returned 0% blocks executed 0% + #####: 3225:internal void arrayNetDeserialLevel1(sArrayt **array, u8 **data, contextt *ctx) { + #####: 3226: sUndefinedt *u = NULL; + #####: 3227: sBoolt *bo = NULL; + #####: 3228: double *D = NULL; + #####: 3229: sDoublet *Do = NULL; + #####: 3230: sDictt *d = NULL; + #####: 3231: sIntt *io = NULL; + #####: 3232: char *s = NULL; + #####: 3233: sStringt *so = NULL; + #####: 3234: sArrayt *a = NULL; + #####: 3235: sBytest *B = NULL; + -: 3236: uint32_t count; + -: 3237: uint32_t arrayCount; + -: 3238: + #####: 3239: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3240: arrayCount = netTypeVarintToUint(data); +call 0 never executed + -: 3241: } + -: 3242: else { + -: 3243: // high nibble + #####: 3244: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3245: arrayCount = varintToUint(data); +call 0 never executed + -: 3246: } + -: 3247: + #####: 3248: if (!arrayCount) { +branch 0 never executed +branch 1 never executed + #####: 3249: *array = allocSArray();; +call 0 never executed + #####: 3250: ret; + -: 3251: } + -: 3252: + #####: 3253: loop(arrayCount) { +branch 0 never executed +branch 1 never executed + -: 3254: char type; + #####: 3255: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3256: type = (**data) & 0xF; + -: 3257: } + -: 3258: else { + -: 3259: // high nibble + #####: 3260: type = (*ctx->nblAddr) >> 4; + -: 3261: } + -: 3262: + #####: 3263: switch(type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed + -: 3264: case S_UNDEFINED: + #####: 3265: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3266: readTypeOnly; + -: 3267: } + -: 3268: else { + -: 3269: // high nibble + #####: 3270: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3271: } + #####: 3272: u = allocSUndefined(); +call 0 never executed + #####: 3273: sArrayPushTiny(array, (smallt *) u); +call 0 never executed + #####: 3274: break; + -: 3275: case S_BOOL: + #####: 3276: if (!ctx->boolAddr) { +branch 0 never executed +branch 1 never executed + -: 3277: // new packed bools + #####: 3278: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3279: read4bPackedBool; + #####: 3280: bo = allocSBool((*ctx->boolAddr) & 0x10); +call 0 never executed + -: 3281: } + -: 3282: else { + -: 3283: // high nibble + #####: 3284: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3285: read8bPackedBool; + #####: 3286: bo = allocSBool((*ctx->boolAddr) & 0x1); +call 0 never executed + -: 3287: } + -: 3288: } + -: 3289: else { + -: 3290: // there was a bool before this one, read bits in nibbles + #####: 3291: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3292: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + #####: 3293: read4bPackedBool; + #####: 3294: bo = allocSBool((*ctx->boolAddr) & 0x10); +call 0 never executed + -: 3295: } + -: 3296: else { + #####: 3297: readTypeOnly; + #####: 3298: bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); +call 0 never executed + -: 3299: } + -: 3300: } + -: 3301: else { + -: 3302: // high nibble + #####: 3303: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3304: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + #####: 3305: read8bPackedBool; + #####: 3306: bo = allocSBool((*ctx->boolAddr) & 0x1); +call 0 never executed + -: 3307: } + -: 3308: else { + #####: 3309: bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); +call 0 never executed + -: 3310: } + -: 3311: } + -: 3312: } + #####: 3313: sArrayPushTiny(array, (smallt *) bo); +call 0 never executed + #####: 3314: break; + -: 3315: case S_DICT: + #####: 3316: d = NULL; + #####: 3317: dictNetDeserialLevel1(&d, data, ctx); +call 0 never executed + #####: 3318: sArrayPushTiny(array, (smallt *) d); +call 0 never executed + #####: 3319: break; + -: 3320: case S_DOUBLE: + #####: 3321: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3322: readTypeOnly; + -: 3323: } + -: 3324: else { + -: 3325: // high nibble + #####: 3326: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3327: } + #####: 3328: D = (double *)(*data); + #####: 3329: *data += sizeof(double); + #####: 3330: Do = allocSDouble(*D); +call 0 never executed + #####: 3331: sArrayPushTiny(array, (smallt *) Do); +call 0 never executed + #####: 3332: break; + -: 3333: case S_INT: { + -: 3334: i64 v; + #####: 3335: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3336: v = netTypeVarintToUint((u8**)data); +call 0 never executed + -: 3337: } + -: 3338: else { + -: 3339: // high nibble + #####: 3340: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3341: v = varintToUint(data); +call 0 never executed + -: 3342: } + #####: 3343: v = (v >> 1) ^ ((v << 63) >> 63); + #####: 3344: io = allocSInt(v); +call 0 never executed + #####: 3345: sArrayPushTiny(array, (smallt *) io); +call 0 never executed + -: 3346: } + #####: 3347: break; + -: 3348: case S_STRING: + #####: 3349: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3350: readTypeOnly; + -: 3351: } + -: 3352: else { + -: 3353: // high nibble + #####: 3354: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3355: } + #####: 3356: s = (char *)(*data); + #####: 3357: *data += strlen(s)+1; + #####: 3358: so = allocSStringTiny(s); +call 0 never executed + #####: 3359: sArrayPushTiny(array, (smallt *) so); +call 0 never executed + #####: 3360: break; + -: 3361: case S_ARRAY: + #####: 3362: a = NULL; + #####: 3363: arrayNetDeserialLevel1(&a, data, ctx); +call 0 never executed + #####: 3364: sArrayPushTiny(array, (smallt *) a); +call 0 never executed + #####: 3365: break; + -: 3366: case S_BYTES: + #####: 3367: B = allocSBytes(); +call 0 never executed + #####: 3368: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3369: count = netTypeVarintToUint((u8**)data); +call 0 never executed + -: 3370: } + -: 3371: else { + -: 3372: // high nibble + #####: 3373: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3374: count = varintToUint((u8**)data); +call 0 never executed + -: 3375: } + #####: 3376: sBytesPushBuffer(&B, data, count); +call 0 never executed + #####: 3377: *data += count; + #####: 3378: sArrayPushTiny(array, (smallt *) B); +call 0 never executed + #####: 3379: break; + -: 3380: } + -: 3381: } + -: 3382:} + -: 3383: +function deserialNetSerialLevel1 called 0 returned 0% blocks executed 0% + #####: 3384:internal smallJsont* deserialNetSerialLevel1(smallJsont *self, smallBytest *data) { + -: 3385: + #####: 3386: if (!data) { +branch 0 never executed +branch 1 never executed + #####: 3387: ret self; + -: 3388: } + -: 3389: + #####: 3390: smallt *o = netDeserialLevel1(data->B); +call 0 never executed + -: 3391: + #####: 3392: if (!o) { +branch 0 never executed +branch 1 never executed + #####: 3393: ret self; + -: 3394: } + -: 3395: + #####: 3396: freeG(self); +call 0 never executed + -: 3397: + #####: 3398: setsoG(self, o); +call 0 never executed + -: 3399: + #####: 3400: ret self; + -: 3401:} + -: 3402: + -: 3403:// level 2 + -: 3404: +function netDeserialLevel2 called 0 returned 0% blocks executed 0% + #####: 3405:internal smallt* netDeserialLevel2(sBytest *obj) { + #####: 3406: smallt *r = NULL; + #####: 3407: double *D = NULL; + #####: 3408: char *s = NULL; + #####: 3409: sBytest *B = NULL; + -: 3410: uint32_t count; + #####: 3411: char *data = NULL; + #####: 3412: contextt ctx = {.nibble=lowNbl, .nblAddr=NULL, .boolShift = 0, .boolAddr=NULL}; + -: 3413: + #####: 3414: switch(obj->data & 0xF) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed +branch 9 never executed +branch 10 never executed + -: 3415: case S_UNDEFINED: + #####: 3416: r = (smallt *) allocSUndefined(); +call 0 never executed + #####: 3417: break; + -: 3418: case S_BOOL: + #####: 3419: r = (smallt *) allocSBool(obj->data & 0x10); +call 0 never executed + #####: 3420: break; + -: 3421: case S_DICT: + #####: 3422: data = (char *)&(obj->data); + -: 3423: //debug - ctx.dbuf = (u8*) data; + #####: 3424: dictNetDeserialLevel2((sDictt **)&r, (u8**)&data, &ctx, /*packed=*/false); +call 0 never executed + #####: 3425: break; + -: 3426: case S_DOUBLE: + #####: 3427: data = &(obj->data)+1; + #####: 3428: D = (double *)data; + #####: 3429: r = (smallt *) allocSDouble(*D); +call 0 never executed + #####: 3430: break; + -: 3431: case S_INT: + #####: 3432: data = &(obj->data); + #####: 3433: i64 v = netTypeVarintToUint((u8**)&data); +call 0 never executed + #####: 3434: v = (v >> 1) ^ ((v << 63) >> 63); + #####: 3435: r = (smallt *) allocSInt(v); +call 0 never executed + #####: 3436: break; + -: 3437: case S_STRING: + #####: 3438: s = (char *)&(obj->data)+1; + #####: 3439: r = (smallt *) allocSStringTiny(s); +call 0 never executed + #####: 3440: break; + -: 3441: case S_ARRAY: + #####: 3442: data = (char *)&(obj->data); + -: 3443: //debug - ctx.dbuf = (u8*) data; + #####: 3444: arrayNetDeserialLevel2((sArrayt **)&r, (u8**)&data, &ctx, /*packed=*/false); +call 0 never executed + #####: 3445: break; + -: 3446: case S_BYTES: + #####: 3447: B = allocSBytes(); +call 0 never executed + #####: 3448: data = &(obj->data); + #####: 3449: count = netTypeVarintToUint((u8**)&data); +call 0 never executed + #####: 3450: sBytesPushBuffer(&B, data, count); +call 0 never executed + #####: 3451: r = (smallt *)B; + #####: 3452: break; + -: 3453: case UNIFORM_DICT: + #####: 3454: data = (char *)&(obj->data); + -: 3455: //debug - ctx.dbuf = (u8*) data; + #####: 3456: uniformDictNetDeserialLevel2((sDictt **)&r, (u8**)&data, &ctx, /*packed=*/false); +call 0 never executed + #####: 3457: break; + -: 3458: case UNIFORM_ARRAY: + #####: 3459: data = (char *)&(obj->data); + -: 3460: //debug - ctx.dbuf = (u8*) data; + #####: 3461: uniformArrayNetDeserialLevel2((sArrayt **)&r, (u8**)&data, &ctx, /*packed=*/false); +call 0 never executed + #####: 3462: break; + -: 3463: } + -: 3464: + #####: 3465: ret r; + -: 3466:} + -: 3467: + -: 3468:/** + -: 3469: * deserialize dictionary from data + -: 3470: * + -: 3471: * a new dictionary is allocated + -: 3472: * + -: 3473: * \param + -: 3474: * dict dictionary holding the elements + -: 3475: * data serialized dictionary + -: 3476: */ +function dictNetDeserialLevel2 called 0 returned 0% blocks executed 0% + #####: 3477:internal void dictNetDeserialLevel2(sDictt **dict, u8 **data, contextt *ctx, bool packed) { + #####: 3478: sUndefinedt *u = NULL; + #####: 3479: sBoolt *bo = NULL; + #####: 3480: double *D = NULL; + #####: 3481: sDoublet *Do = NULL; + #####: 3482: sDictt *d = NULL; + #####: 3483: sIntt *io = NULL; + #####: 3484: char *s = NULL; + #####: 3485: sStringt *so = NULL; + #####: 3486: sArrayt *a = NULL; + #####: 3487: sBytest *B = NULL; + -: 3488: uint32_t count; + -: 3489: uint32_t dictCount; + -: 3490: + #####: 3491: if (packed) { +branch 0 never executed +branch 1 never executed + #####: 3492: dictCount = varintToUint(data); +call 0 never executed + -: 3493: } + -: 3494: else { + #####: 3495: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3496: dictCount = netTypeVarintToUint(data); +call 0 never executed + -: 3497: } + -: 3498: else { + -: 3499: // high nibble + -: 3500: // type = *(ctx->dbuf + ctx->nblOffset) >> 4; + -: 3501: #define readTypeInHighNbl\ + -: 3502: ctx->nibble = lowNbl;\ + -: 3503: if (ctx->nblAddr == *data)\ + -: 3504: /* data points to the type, next byte is count */\ + -: 3505: (*data)++ + #####: 3506: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3507: dictCount = varintToUint(data); +call 0 never executed + -: 3508: } + -: 3509: } + -: 3510: + #####: 3511: if (!dictCount) { +branch 0 never executed +branch 1 never executed + #####: 3512: *dict = allocSDict(); +call 0 never executed + #####: 3513: ret; + -: 3514: } + -: 3515: + #####: 3516: loop(dictCount) { +branch 0 never executed +branch 1 never executed + #####: 3517: char *key = (char*)*data; + #####: 3518: *data += strlen(key)+1; + -: 3519: char type; + #####: 3520: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3521: type = (**data) & 0xF; + -: 3522: } + -: 3523: else { + -: 3524: // high nibble + #####: 3525: type = (*ctx->nblAddr) >> 4; + -: 3526: } + -: 3527: + #####: 3528: switch(type) { +branch 0 never executed +branch 1 never executed +branch 2 never executed +branch 3 never executed +branch 4 never executed +branch 5 never executed +branch 6 never executed +branch 7 never executed +branch 8 never executed +branch 9 never executed +branch 10 never executed + -: 3529: case S_UNDEFINED: + #####: 3530: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 3531: #define readTypeOnly\ + -: 3532: ctx->nibble = highNbl;\ + -: 3533: ctx->nblAddr = *data;\ + -: 3534: (*data)++ + #####: 3535: readTypeOnly; + -: 3536: } + -: 3537: else { + -: 3538: // high nibble + #####: 3539: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3540: } + #####: 3541: u = allocSUndefined(); +call 0 never executed + #####: 3542: sDictPushTiny(dict, key, (smallt *) u); +call 0 never executed + #####: 3543: break; + -: 3544: case S_BOOL: + #####: 3545: if (!ctx->boolAddr) { +branch 0 never executed +branch 1 never executed + -: 3546: // new packed bools + #####: 3547: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + -: 3548: #define read4bPackedBool\ + -: 3549: ctx->boolShift = 5;\ + -: 3550: ctx->boolAddr = *data;\ + -: 3551: (*data)++ + #####: 3552: read4bPackedBool; + #####: 3553: bo = allocSBool((*ctx->boolAddr) & 0x10); +call 0 never executed + -: 3554: } + -: 3555: else { + -: 3556: // high nibble + #####: 3557: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3558: #define read8bPackedBool\ + -: 3559: ctx->boolShift = 1;\ + -: 3560: ctx->boolAddr = *data;\ + -: 3561: (*data)++ + #####: 3562: read8bPackedBool; + #####: 3563: bo = allocSBool((*ctx->boolAddr) & 0x1); +call 0 never executed + -: 3564: } + -: 3565: } + -: 3566: else { + -: 3567: // there was a bool before this one, read bits in nibbles + #####: 3568: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3569: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + #####: 3570: read4bPackedBool; + #####: 3571: bo = allocSBool((*ctx->boolAddr) & 0x10); +call 0 never executed + -: 3572: } + -: 3573: else { + #####: 3574: readTypeOnly; + #####: 3575: bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); +call 0 never executed + -: 3576: } + -: 3577: } + -: 3578: else { + -: 3579: // high nibble + #####: 3580: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3581: if (ctx->boolShift == 8) { +branch 0 never executed +branch 1 never executed + #####: 3582: read8bPackedBool; + #####: 3583: bo = allocSBool((*ctx->boolAddr) & 0x1); +call 0 never executed + -: 3584: } + -: 3585: else { + -: 3586: // high nibble + #####: 3587: bo = allocSBool((*ctx->boolAddr) & (0x1 << (ctx->boolShift++))); +call 0 never executed + -: 3588: } + -: 3589: } + -: 3590: } + #####: 3591: sDictPushTiny(dict, key, (smallt *) bo); +call 0 never executed + #####: 3592: break; + -: 3593: case S_DICT: + #####: 3594: d = NULL; + #####: 3595: dictNetDeserialLevel2(&d, data, ctx, /*packed=*/false); +call 0 never executed + #####: 3596: sDictPushTiny(dict, key, (smallt *) d); +call 0 never executed + #####: 3597: break; + -: 3598: case S_DOUBLE: + #####: 3599: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3600: readTypeOnly; + -: 3601: } + -: 3602: else { + -: 3603: // high nibble + #####: 3604: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3605: } + #####: 3606: D = (double *)(*data); + #####: 3607: *data += sizeof(double); + #####: 3608: Do = allocSDouble(*D); +call 0 never executed + #####: 3609: sDictPushTiny(dict, key, (smallt *) Do); +call 0 never executed + #####: 3610: break; + -: 3611: case S_INT: { + -: 3612: i64 v; + #####: 3613: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3614: v = netTypeVarintToUint((u8**)data); +call 0 never executed + -: 3615: } + -: 3616: else { + -: 3617: // high nibble + #####: 3618: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3619: v = varintToUint(data); +call 0 never executed + -: 3620: } + #####: 3621: v = (v >> 1) ^ ((v << 63) >> 63); + #####: 3622: io = allocSInt(v); +call 0 never executed + #####: 3623: sDictPushTiny(dict, key, (smallt *) io); +call 0 never executed + -: 3624: } + #####: 3625: break; + -: 3626: case S_STRING: + #####: 3627: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3628: readTypeOnly; + -: 3629: } + -: 3630: else { + -: 3631: // high nibble + #####: 3632: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + -: 3633: } + #####: 3634: s = (char *)(*data); + #####: 3635: *data += strlen(s)+1; + #####: 3636: so = allocSStringTiny(s); +call 0 never executed + #####: 3637: sDictPushTiny(dict, key, (smallt *) so); +call 0 never executed + #####: 3638: break; + -: 3639: case S_ARRAY: + #####: 3640: a = NULL; + #####: 3641: arrayNetDeserialLevel2(&a, data, ctx, /*packed=*/false); +call 0 never executed + #####: 3642: sDictPushTiny(dict, key, (smallt *) a); +call 0 never executed + #####: 3643: break; + -: 3644: case S_BYTES: + #####: 3645: B = allocSBytes(); +call 0 never executed + #####: 3646: if (ctx->nibble == lowNbl) { +branch 0 never executed +branch 1 never executed + #####: 3647: count = netTypeVarintToUint((u8**)data); +call 0 never executed + -: 3648: } + -: 3649: else { + -: 3650: // high nibble + #####: 3651: readTypeInHighNbl; +branch 0 never executed +branch 1 never executed + #####: 3652: count = varintToUint((u8**)data); +call 0 never executed + -: 3653: } + #####: 3654: sBytesPushBuffer(&B, data, count); +call 0 never executed + #####: 3655: *data += count; + #####: 3656: sDictPushTiny(dict, key, (smallt *) B); +call 0 never executed + #####: 3657: break; + -: 3658: case UNIFORM_DICT: + #####: 3659: d = NULL; + #####: 3660: uniformDictNetDeserialLevel2(&d, data, ctx, /*packed=*/false); +call 0 never executed + #####: 3661: sDictPushTiny(dict, key, (smallt *) d); +call 0 never executed + #####: 3662: break; + -: 3663: case UNIFORM_ARRAY: