Delete unused parts of zipmap (#973)
Deletes zipmapSet, zipmapGet, etc. Only keep iterator and validate integrity, what we use when loading an old RDB file. Adjust unit tests to not use zipmapSet, etc. Solves a build failure where when compiling with fortify source. --------- Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
This commit is contained in:
parent
fea49bce2c
commit
5d458c6292
@ -70,8 +70,7 @@ int test_BenchmarkziplistValidateIntegrity(int argc, char **argv, int flags);
|
|||||||
int test_BenchmarkziplistCompareWithString(int argc, char **argv, int flags);
|
int test_BenchmarkziplistCompareWithString(int argc, char **argv, int flags);
|
||||||
int test_BenchmarkziplistCompareWithNumber(int argc, char **argv, int flags);
|
int test_BenchmarkziplistCompareWithNumber(int argc, char **argv, int flags);
|
||||||
int test_ziplistStress__ziplistCascadeUpdate(int argc, char **argv, int flags);
|
int test_ziplistStress__ziplistCascadeUpdate(int argc, char **argv, int flags);
|
||||||
int test_zipmapLookUpLargeKey(int argc, char *argv[], int flags);
|
int test_zipmapIterateWithLargeKey(int argc, char *argv[], int flags);
|
||||||
int test_zipmapPerformDirectLookup(int argc, char *argv[], int flags);
|
|
||||||
int test_zipmapIterateThroughElements(int argc, char *argv[], int flags);
|
int test_zipmapIterateThroughElements(int argc, char *argv[], int flags);
|
||||||
int test_zmallocInitialUsedMemory(int argc, char **argv, int flags);
|
int test_zmallocInitialUsedMemory(int argc, char **argv, int flags);
|
||||||
int test_zmallocAllocReallocCallocAndFree(int argc, char **argv, int flags);
|
int test_zmallocAllocReallocCallocAndFree(int argc, char **argv, int flags);
|
||||||
@ -86,7 +85,7 @@ unitTest __test_sds_c[] = {{"test_sds", test_sds}, {"test_typesAndAllocSize", te
|
|||||||
unitTest __test_sha1_c[] = {{"test_sha1", test_sha1}, {NULL, NULL}};
|
unitTest __test_sha1_c[] = {{"test_sha1", test_sha1}, {NULL, NULL}};
|
||||||
unitTest __test_util_c[] = {{"test_string2ll", test_string2ll}, {"test_string2l", test_string2l}, {"test_ll2string", test_ll2string}, {"test_ld2string", test_ld2string}, {"test_fixedpoint_d2string", test_fixedpoint_d2string}, {"test_version2num", test_version2num}, {"test_reclaimFilePageCache", test_reclaimFilePageCache}, {NULL, NULL}};
|
unitTest __test_util_c[] = {{"test_string2ll", test_string2ll}, {"test_string2l", test_string2l}, {"test_ll2string", test_ll2string}, {"test_ld2string", test_ld2string}, {"test_fixedpoint_d2string", test_fixedpoint_d2string}, {"test_version2num", test_version2num}, {"test_reclaimFilePageCache", test_reclaimFilePageCache}, {NULL, NULL}};
|
||||||
unitTest __test_ziplist_c[] = {{"test_ziplistCreateIntList", test_ziplistCreateIntList}, {"test_ziplistPop", test_ziplistPop}, {"test_ziplistGetElementAtIndex3", test_ziplistGetElementAtIndex3}, {"test_ziplistGetElementOutOfRange", test_ziplistGetElementOutOfRange}, {"test_ziplistGetLastElement", test_ziplistGetLastElement}, {"test_ziplistGetFirstElement", test_ziplistGetFirstElement}, {"test_ziplistGetElementOutOfRangeReverse", test_ziplistGetElementOutOfRangeReverse}, {"test_ziplistIterateThroughFullList", test_ziplistIterateThroughFullList}, {"test_ziplistIterateThroughListFrom1ToEnd", test_ziplistIterateThroughListFrom1ToEnd}, {"test_ziplistIterateThroughListFrom2ToEnd", test_ziplistIterateThroughListFrom2ToEnd}, {"test_ziplistIterateThroughStartOutOfRange", test_ziplistIterateThroughStartOutOfRange}, {"test_ziplistIterateBackToFront", test_ziplistIterateBackToFront}, {"test_ziplistIterateBackToFrontDeletingAllItems", test_ziplistIterateBackToFrontDeletingAllItems}, {"test_ziplistDeleteInclusiveRange0To0", test_ziplistDeleteInclusiveRange0To0}, {"test_ziplistDeleteInclusiveRange0To1", test_ziplistDeleteInclusiveRange0To1}, {"test_ziplistDeleteInclusiveRange1To2", test_ziplistDeleteInclusiveRange1To2}, {"test_ziplistDeleteWithStartIndexOutOfRange", test_ziplistDeleteWithStartIndexOutOfRange}, {"test_ziplistDeleteWithNumOverflow", test_ziplistDeleteWithNumOverflow}, {"test_ziplistDeleteFooWhileIterating", test_ziplistDeleteFooWhileIterating}, {"test_ziplistReplaceWithSameSize", test_ziplistReplaceWithSameSize}, {"test_ziplistReplaceWithDifferentSize", test_ziplistReplaceWithDifferentSize}, {"test_ziplistRegressionTestForOver255ByteStrings", test_ziplistRegressionTestForOver255ByteStrings}, {"test_ziplistRegressionTestDeleteNextToLastEntries", test_ziplistRegressionTestDeleteNextToLastEntries}, {"test_ziplistCreateLongListAndCheckIndices", test_ziplistCreateLongListAndCheckIndices}, {"test_ziplistCompareStringWithZiplistEntries", test_ziplistCompareStringWithZiplistEntries}, {"test_ziplistMergeTest", test_ziplistMergeTest}, {"test_ziplistStressWithRandomPayloadsOfDifferentEncoding", test_ziplistStressWithRandomPayloadsOfDifferentEncoding}, {"test_ziplistCascadeUpdateEdgeCases", test_ziplistCascadeUpdateEdgeCases}, {"test_ziplistInsertEdgeCase", test_ziplistInsertEdgeCase}, {"test_ziplistStressWithVariableSize", test_ziplistStressWithVariableSize}, {"test_BenchmarkziplistFind", test_BenchmarkziplistFind}, {"test_BenchmarkziplistIndex", test_BenchmarkziplistIndex}, {"test_BenchmarkziplistValidateIntegrity", test_BenchmarkziplistValidateIntegrity}, {"test_BenchmarkziplistCompareWithString", test_BenchmarkziplistCompareWithString}, {"test_BenchmarkziplistCompareWithNumber", test_BenchmarkziplistCompareWithNumber}, {"test_ziplistStress__ziplistCascadeUpdate", test_ziplistStress__ziplistCascadeUpdate}, {NULL, NULL}};
|
unitTest __test_ziplist_c[] = {{"test_ziplistCreateIntList", test_ziplistCreateIntList}, {"test_ziplistPop", test_ziplistPop}, {"test_ziplistGetElementAtIndex3", test_ziplistGetElementAtIndex3}, {"test_ziplistGetElementOutOfRange", test_ziplistGetElementOutOfRange}, {"test_ziplistGetLastElement", test_ziplistGetLastElement}, {"test_ziplistGetFirstElement", test_ziplistGetFirstElement}, {"test_ziplistGetElementOutOfRangeReverse", test_ziplistGetElementOutOfRangeReverse}, {"test_ziplistIterateThroughFullList", test_ziplistIterateThroughFullList}, {"test_ziplistIterateThroughListFrom1ToEnd", test_ziplistIterateThroughListFrom1ToEnd}, {"test_ziplistIterateThroughListFrom2ToEnd", test_ziplistIterateThroughListFrom2ToEnd}, {"test_ziplistIterateThroughStartOutOfRange", test_ziplistIterateThroughStartOutOfRange}, {"test_ziplistIterateBackToFront", test_ziplistIterateBackToFront}, {"test_ziplistIterateBackToFrontDeletingAllItems", test_ziplistIterateBackToFrontDeletingAllItems}, {"test_ziplistDeleteInclusiveRange0To0", test_ziplistDeleteInclusiveRange0To0}, {"test_ziplistDeleteInclusiveRange0To1", test_ziplistDeleteInclusiveRange0To1}, {"test_ziplistDeleteInclusiveRange1To2", test_ziplistDeleteInclusiveRange1To2}, {"test_ziplistDeleteWithStartIndexOutOfRange", test_ziplistDeleteWithStartIndexOutOfRange}, {"test_ziplistDeleteWithNumOverflow", test_ziplistDeleteWithNumOverflow}, {"test_ziplistDeleteFooWhileIterating", test_ziplistDeleteFooWhileIterating}, {"test_ziplistReplaceWithSameSize", test_ziplistReplaceWithSameSize}, {"test_ziplistReplaceWithDifferentSize", test_ziplistReplaceWithDifferentSize}, {"test_ziplistRegressionTestForOver255ByteStrings", test_ziplistRegressionTestForOver255ByteStrings}, {"test_ziplistRegressionTestDeleteNextToLastEntries", test_ziplistRegressionTestDeleteNextToLastEntries}, {"test_ziplistCreateLongListAndCheckIndices", test_ziplistCreateLongListAndCheckIndices}, {"test_ziplistCompareStringWithZiplistEntries", test_ziplistCompareStringWithZiplistEntries}, {"test_ziplistMergeTest", test_ziplistMergeTest}, {"test_ziplistStressWithRandomPayloadsOfDifferentEncoding", test_ziplistStressWithRandomPayloadsOfDifferentEncoding}, {"test_ziplistCascadeUpdateEdgeCases", test_ziplistCascadeUpdateEdgeCases}, {"test_ziplistInsertEdgeCase", test_ziplistInsertEdgeCase}, {"test_ziplistStressWithVariableSize", test_ziplistStressWithVariableSize}, {"test_BenchmarkziplistFind", test_BenchmarkziplistFind}, {"test_BenchmarkziplistIndex", test_BenchmarkziplistIndex}, {"test_BenchmarkziplistValidateIntegrity", test_BenchmarkziplistValidateIntegrity}, {"test_BenchmarkziplistCompareWithString", test_BenchmarkziplistCompareWithString}, {"test_BenchmarkziplistCompareWithNumber", test_BenchmarkziplistCompareWithNumber}, {"test_ziplistStress__ziplistCascadeUpdate", test_ziplistStress__ziplistCascadeUpdate}, {NULL, NULL}};
|
||||||
unitTest __test_zipmap_c[] = {{"test_zipmapLookUpLargeKey", test_zipmapLookUpLargeKey}, {"test_zipmapPerformDirectLookup", test_zipmapPerformDirectLookup}, {"test_zipmapIterateThroughElements", test_zipmapIterateThroughElements}, {NULL, NULL}};
|
unitTest __test_zipmap_c[] = {{"test_zipmapIterateWithLargeKey", test_zipmapIterateWithLargeKey}, {"test_zipmapIterateThroughElements", test_zipmapIterateThroughElements}, {NULL, NULL}};
|
||||||
unitTest __test_zmalloc_c[] = {{"test_zmallocInitialUsedMemory", test_zmallocInitialUsedMemory}, {"test_zmallocAllocReallocCallocAndFree", test_zmallocAllocReallocCallocAndFree}, {"test_zmallocAllocZeroByteAndFree", test_zmallocAllocZeroByteAndFree}, {NULL, NULL}};
|
unitTest __test_zmalloc_c[] = {{"test_zmallocInitialUsedMemory", test_zmallocInitialUsedMemory}, {"test_zmallocAllocReallocCallocAndFree", test_zmallocAllocReallocCallocAndFree}, {"test_zmallocAllocZeroByteAndFree", test_zmallocAllocZeroByteAndFree}, {NULL, NULL}};
|
||||||
|
|
||||||
struct unitTestSuite {
|
struct unitTestSuite {
|
||||||
|
@ -1,129 +1,93 @@
|
|||||||
#include "../zipmap.c"
|
#include "../zipmap.c"
|
||||||
#include "test_help.h"
|
#include "test_help.h"
|
||||||
|
|
||||||
static void zipmapRepr(unsigned char *p) {
|
int test_zipmapIterateWithLargeKey(int argc, char *argv[], int flags) {
|
||||||
unsigned int l;
|
|
||||||
|
|
||||||
p++;
|
|
||||||
while (1) {
|
|
||||||
if (p[0] == ZIPMAP_END) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
unsigned char e;
|
|
||||||
|
|
||||||
l = zipmapDecodeLength(p);
|
|
||||||
p += zipmapEncodeLength(NULL, l);
|
|
||||||
if (l != 0 && fwrite(p, l, 1, stdout) == 0) perror("fwrite");
|
|
||||||
p += l;
|
|
||||||
|
|
||||||
l = zipmapDecodeLength(p);
|
|
||||||
p += zipmapEncodeLength(NULL, l);
|
|
||||||
e = *p++;
|
|
||||||
if (l != 0 && fwrite(p, l, 1, stdout) == 0) perror("fwrite");
|
|
||||||
p += l + e;
|
|
||||||
if (e) {
|
|
||||||
while (e--);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int test_zipmapLookUpLargeKey(int argc, char *argv[], int flags) {
|
|
||||||
unsigned char *zm;
|
|
||||||
UNUSED(argc);
|
|
||||||
UNUSED(argv);
|
|
||||||
UNUSED(flags);
|
|
||||||
zm = zipmapNew();
|
|
||||||
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"name", 4, (unsigned char *)"foo", 3, NULL);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"surname", 7, (unsigned char *)"foo", 3, NULL);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"age", 3, (unsigned char *)"foo", 3, NULL);
|
|
||||||
zipmapRepr(zm);
|
|
||||||
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"hello", 5, (unsigned char *)"world!", 6, NULL);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"foo", 3, (unsigned char *)"bar", 3, NULL);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"foo", 3, (unsigned char *)"!", 1, NULL);
|
|
||||||
zipmapRepr(zm);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"foo", 3, (unsigned char *)"12345", 5, NULL);
|
|
||||||
zipmapRepr(zm);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"new", 3, (unsigned char *)"xx", 2, NULL);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"noval", 5, (unsigned char *)"", 0, NULL);
|
|
||||||
zipmapRepr(zm);
|
|
||||||
zm = zipmapDel(zm, (unsigned char *)"new", 3, NULL);
|
|
||||||
zipmapRepr(zm);
|
|
||||||
|
|
||||||
unsigned char buf[512];
|
|
||||||
unsigned char *value;
|
|
||||||
unsigned int vlen, i;
|
|
||||||
for (i = 0; i < 512; i++) buf[i] = 'a';
|
|
||||||
zm = zipmapSet(zm, buf, 512, (unsigned char *)"long", 4, NULL);
|
|
||||||
if (zipmapGet(zm, buf, 512, &value, &vlen)) {
|
|
||||||
TEST_ASSERT(4 == vlen);
|
|
||||||
TEST_ASSERT(strncmp("long", (const char *)value, vlen) == 0);
|
|
||||||
}
|
|
||||||
zfree(zm);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
int test_zipmapPerformDirectLookup(int argc, char *argv[], int flags) {
|
|
||||||
unsigned char *zm;
|
|
||||||
UNUSED(argc);
|
UNUSED(argc);
|
||||||
UNUSED(argv);
|
UNUSED(argv);
|
||||||
UNUSED(flags);
|
UNUSED(flags);
|
||||||
zm = zipmapNew();
|
|
||||||
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"name", 4, (unsigned char *)"foo", 3, NULL);
|
char zm[] = "\x04"
|
||||||
zm = zipmapSet(zm, (unsigned char *)"surname", 7, (unsigned char *)"foo", 3, NULL);
|
"\x04"
|
||||||
zm = zipmapSet(zm, (unsigned char *)"age", 3, (unsigned char *)"foo", 3, NULL);
|
"name"
|
||||||
zipmapRepr(zm);
|
"\x03\x00"
|
||||||
|
"foo"
|
||||||
|
"\x07"
|
||||||
|
"surname"
|
||||||
|
"\x03\x00"
|
||||||
|
"foo"
|
||||||
|
"noval"
|
||||||
|
"\x00\x00"
|
||||||
|
"\xfe\x00\x02\x00\x00"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"\x04\x00"
|
||||||
|
"long"
|
||||||
|
"\xff";
|
||||||
|
TEST_ASSERT(zipmapValidateIntegrity((unsigned char *)zm, sizeof zm - 1, 1));
|
||||||
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"hello", 5, (unsigned char *)"world!", 6, NULL);
|
unsigned char *p = zipmapRewind((unsigned char *)zm);
|
||||||
zm = zipmapSet(zm, (unsigned char *)"foo", 3, (unsigned char *)"bar", 3, NULL);
|
unsigned char *key, *value;
|
||||||
zm = zipmapSet(zm, (unsigned char *)"foo", 3, (unsigned char *)"!", 1, NULL);
|
unsigned int klen, vlen;
|
||||||
zipmapRepr(zm);
|
char buf[512];
|
||||||
zm = zipmapSet(zm, (unsigned char *)"foo", 3, (unsigned char *)"12345", 5, NULL);
|
memset(buf, 'a', 512);
|
||||||
zipmapRepr(zm);
|
char *expected_key[] = {"name", "surname", "noval", buf};
|
||||||
zm = zipmapSet(zm, (unsigned char *)"new", 3, (unsigned char *)"xx", 2, NULL);
|
char *expected_value[] = {"foo", "foo", NULL, "long"};
|
||||||
zm = zipmapSet(zm, (unsigned char *)"noval", 5, (unsigned char *)"", 0, NULL);
|
unsigned int expected_klen[] = {4, 7, 5, 512};
|
||||||
zipmapRepr(zm);
|
unsigned int expected_vlen[] = {3, 3, 0, 4};
|
||||||
zm = zipmapDel(zm, (unsigned char *)"new", 3, NULL);
|
int iter = 0;
|
||||||
zipmapRepr(zm);
|
|
||||||
unsigned char *value;
|
|
||||||
unsigned int vlen;
|
|
||||||
|
|
||||||
if (zipmapGet(zm, (unsigned char *)"foo", 3, &value, &vlen)) {
|
while ((p = zipmapNext(p, &key, &klen, &value, &vlen)) != NULL) {
|
||||||
TEST_ASSERT(5 == vlen);
|
char *tmp = expected_key[iter];
|
||||||
TEST_ASSERT(!strncmp("12345", (const char *)value, vlen));
|
TEST_ASSERT(klen == expected_klen[iter]);
|
||||||
|
TEST_ASSERT(strncmp((const char *)tmp, (const char *)key, klen) == 0);
|
||||||
|
tmp = expected_value[iter];
|
||||||
|
TEST_ASSERT(vlen == expected_vlen[iter]);
|
||||||
|
TEST_ASSERT(strncmp((const char *)tmp, (const char *)value, vlen) == 0);
|
||||||
|
iter++;
|
||||||
}
|
}
|
||||||
zfree(zm);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_zipmapIterateThroughElements(int argc, char *argv[], int flags) {
|
int test_zipmapIterateThroughElements(int argc, char *argv[], int flags) {
|
||||||
unsigned char *zm;
|
|
||||||
UNUSED(argc);
|
UNUSED(argc);
|
||||||
UNUSED(argv);
|
UNUSED(argv);
|
||||||
UNUSED(flags);
|
UNUSED(flags);
|
||||||
zm = zipmapNew();
|
|
||||||
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"name", 4, (unsigned char *)"foo", 3, NULL);
|
char zm[] = "\x06"
|
||||||
zm = zipmapSet(zm, (unsigned char *)"surname", 7, (unsigned char *)"foo", 3, NULL);
|
"\x04"
|
||||||
zm = zipmapSet(zm, (unsigned char *)"age", 3, (unsigned char *)"foo", 3, NULL);
|
"name"
|
||||||
zipmapRepr(zm);
|
"\x03\x00"
|
||||||
|
"foo"
|
||||||
|
"\x07"
|
||||||
|
"surname"
|
||||||
|
"\x03\x00"
|
||||||
|
"foo"
|
||||||
|
"\x03"
|
||||||
|
"age"
|
||||||
|
"\x03\x00"
|
||||||
|
"foo"
|
||||||
|
"\x05"
|
||||||
|
"hello"
|
||||||
|
"\x06\x00"
|
||||||
|
"world!"
|
||||||
|
"\x03"
|
||||||
|
"foo"
|
||||||
|
"\x05\x00"
|
||||||
|
"12345"
|
||||||
|
"\x05"
|
||||||
|
"noval"
|
||||||
|
"\x00\x00"
|
||||||
|
"\xff";
|
||||||
|
TEST_ASSERT(zipmapValidateIntegrity((unsigned char *)zm, sizeof zm - 1, 1));
|
||||||
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"hello", 5, (unsigned char *)"world!", 6, NULL);
|
unsigned char *i = zipmapRewind((unsigned char *)zm);
|
||||||
zm = zipmapSet(zm, (unsigned char *)"foo", 3, (unsigned char *)"bar", 3, NULL);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"foo", 3, (unsigned char *)"!", 1, NULL);
|
|
||||||
zipmapRepr(zm);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"foo", 3, (unsigned char *)"12345", 5, NULL);
|
|
||||||
zipmapRepr(zm);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"new", 3, (unsigned char *)"xx", 2, NULL);
|
|
||||||
zm = zipmapSet(zm, (unsigned char *)"noval", 5, (unsigned char *)"", 0, NULL);
|
|
||||||
zipmapRepr(zm);
|
|
||||||
zm = zipmapDel(zm, (unsigned char *)"new", 3, NULL);
|
|
||||||
zipmapRepr(zm);
|
|
||||||
|
|
||||||
unsigned char *i = zipmapRewind(zm);
|
|
||||||
unsigned char *key, *value;
|
unsigned char *key, *value;
|
||||||
unsigned int klen, vlen;
|
unsigned int klen, vlen;
|
||||||
char *expected_key[] = {"name", "surname", "age", "hello", "foo", "noval"};
|
char *expected_key[] = {"name", "surname", "age", "hello", "foo", "noval"};
|
||||||
@ -141,6 +105,5 @@ int test_zipmapIterateThroughElements(int argc, char *argv[], int flags) {
|
|||||||
TEST_ASSERT(strncmp((const char *)tmp, (const char *)value, vlen) == 0);
|
TEST_ASSERT(strncmp((const char *)tmp, (const char *)value, vlen) == 0);
|
||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
zfree(zm);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
209
src/zipmap.c
209
src/zipmap.c
@ -83,24 +83,11 @@
|
|||||||
#define ZIPMAP_BIGLEN 254
|
#define ZIPMAP_BIGLEN 254
|
||||||
#define ZIPMAP_END 255
|
#define ZIPMAP_END 255
|
||||||
|
|
||||||
/* The following defines the max value for the <free> field described in the
|
|
||||||
* comments above, that is, the max number of trailing bytes in a value. */
|
|
||||||
#define ZIPMAP_VALUE_MAX_FREE 4
|
|
||||||
|
|
||||||
/* The following macro returns the number of bytes needed to encode the length
|
/* The following macro returns the number of bytes needed to encode the length
|
||||||
* for the integer value _l, that is, 1 byte for lengths < ZIPMAP_BIGLEN and
|
* for the integer value _l, that is, 1 byte for lengths < ZIPMAP_BIGLEN and
|
||||||
* 5 bytes for all the other lengths. */
|
* 5 bytes for all the other lengths. */
|
||||||
#define ZIPMAP_LEN_BYTES(_l) (((_l) < ZIPMAP_BIGLEN) ? 1 : sizeof(unsigned int) + 1)
|
#define ZIPMAP_LEN_BYTES(_l) (((_l) < ZIPMAP_BIGLEN) ? 1 : sizeof(unsigned int) + 1)
|
||||||
|
|
||||||
/* Create a new empty zipmap. */
|
|
||||||
unsigned char *zipmapNew(void) {
|
|
||||||
unsigned char *zm = zmalloc(2);
|
|
||||||
|
|
||||||
zm[0] = 0; /* Length */
|
|
||||||
zm[1] = ZIPMAP_END;
|
|
||||||
return zm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode the encoded length pointed by 'p' */
|
/* Decode the encoded length pointed by 'p' */
|
||||||
static unsigned int zipmapDecodeLength(unsigned char *p) {
|
static unsigned int zipmapDecodeLength(unsigned char *p) {
|
||||||
unsigned int len = *p;
|
unsigned int len = *p;
|
||||||
@ -111,10 +98,6 @@ static unsigned int zipmapDecodeLength(unsigned char *p) {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int zipmapGetEncodedLengthSize(unsigned char *p) {
|
|
||||||
return (*p < ZIPMAP_BIGLEN) ? 1 : 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Encode the length 'l' writing it in 'p'. If p is NULL it just returns
|
/* Encode the length 'l' writing it in 'p'. If p is NULL it just returns
|
||||||
* the amount of bytes required to encode such a length. */
|
* the amount of bytes required to encode such a length. */
|
||||||
static unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) {
|
static unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) {
|
||||||
@ -133,49 +116,8 @@ static unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search for a matching key, returning a pointer to the entry inside the
|
static unsigned int zipmapGetEncodedLengthSize(unsigned char *p) {
|
||||||
* zipmap. Returns NULL if the key is not found.
|
return (*p < ZIPMAP_BIGLEN) ? 1 : 5;
|
||||||
*
|
|
||||||
* If NULL is returned, and totlen is not NULL, it is set to the entire
|
|
||||||
* size of the zipmap, so that the calling function will be able to
|
|
||||||
* reallocate the original zipmap to make room for more entries. */
|
|
||||||
static unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned int *totlen) {
|
|
||||||
unsigned char *p = zm + 1, *k = NULL;
|
|
||||||
unsigned int l, llen;
|
|
||||||
|
|
||||||
while (*p != ZIPMAP_END) {
|
|
||||||
unsigned char free;
|
|
||||||
|
|
||||||
/* Match or skip the key */
|
|
||||||
l = zipmapDecodeLength(p);
|
|
||||||
llen = zipmapEncodeLength(NULL, l);
|
|
||||||
if (key != NULL && k == NULL && l == klen && !memcmp(p + llen, key, l)) {
|
|
||||||
/* Only return when the user doesn't care
|
|
||||||
* for the total length of the zipmap. */
|
|
||||||
if (totlen != NULL) {
|
|
||||||
k = p;
|
|
||||||
} else {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p += llen + l;
|
|
||||||
/* Skip the value as well */
|
|
||||||
l = zipmapDecodeLength(p);
|
|
||||||
p += zipmapEncodeLength(NULL, l);
|
|
||||||
free = p[0];
|
|
||||||
p += l + 1 + free; /* +1 to skip the free byte */
|
|
||||||
}
|
|
||||||
if (totlen != NULL) *totlen = (unsigned int)(p - zm) + 1;
|
|
||||||
return k;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long zipmapRequiredLength(unsigned int klen, unsigned int vlen) {
|
|
||||||
unsigned int l;
|
|
||||||
|
|
||||||
l = klen + vlen + 3;
|
|
||||||
if (klen >= ZIPMAP_BIGLEN) l += 4;
|
|
||||||
if (vlen >= ZIPMAP_BIGLEN) l += 4;
|
|
||||||
return l;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the total amount used by a key (encoded length + payload) */
|
/* Return the total amount used by a key (encoded length + payload) */
|
||||||
@ -195,112 +137,6 @@ static unsigned int zipmapRawValueLength(unsigned char *p) {
|
|||||||
return used;
|
return used;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If 'p' points to a key, this function returns the total amount of
|
|
||||||
* bytes used to store this entry (entry = key + associated value + trailing
|
|
||||||
* free space if any). */
|
|
||||||
static unsigned int zipmapRawEntryLength(unsigned char *p) {
|
|
||||||
unsigned int l = zipmapRawKeyLength(p);
|
|
||||||
return l + zipmapRawValueLength(p + l);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned char *zipmapResize(unsigned char *zm, unsigned int len) {
|
|
||||||
zm = zrealloc(zm, len);
|
|
||||||
zm[len - 1] = ZIPMAP_END;
|
|
||||||
return zm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set key to value, creating the key if it does not already exist.
|
|
||||||
* If 'update' is not NULL, *update is set to 1 if the key was
|
|
||||||
* already preset, otherwise to 0. */
|
|
||||||
unsigned char *
|
|
||||||
zipmapSet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char *val, unsigned int vlen, int *update) {
|
|
||||||
unsigned int zmlen, offset;
|
|
||||||
unsigned int freelen, reqlen = zipmapRequiredLength(klen, vlen);
|
|
||||||
unsigned int empty, vempty;
|
|
||||||
unsigned char *p;
|
|
||||||
|
|
||||||
freelen = reqlen;
|
|
||||||
if (update) *update = 0;
|
|
||||||
p = zipmapLookupRaw(zm, key, klen, &zmlen);
|
|
||||||
if (p == NULL) {
|
|
||||||
/* Key not found: enlarge */
|
|
||||||
zm = zipmapResize(zm, zmlen + reqlen);
|
|
||||||
p = zm + zmlen - 1;
|
|
||||||
zmlen = zmlen + reqlen;
|
|
||||||
|
|
||||||
/* Increase zipmap length (this is an insert) */
|
|
||||||
if (zm[0] < ZIPMAP_BIGLEN) zm[0]++;
|
|
||||||
} else {
|
|
||||||
/* Key found. Is there enough space for the new value? */
|
|
||||||
/* Compute the total length: */
|
|
||||||
if (update) *update = 1;
|
|
||||||
freelen = zipmapRawEntryLength(p);
|
|
||||||
if (freelen < reqlen) {
|
|
||||||
/* Store the offset of this key within the current zipmap, so
|
|
||||||
* it can be resized. Then, move the tail backwards so this
|
|
||||||
* pair fits at the current position. */
|
|
||||||
offset = p - zm;
|
|
||||||
zm = zipmapResize(zm, zmlen - freelen + reqlen);
|
|
||||||
p = zm + offset;
|
|
||||||
|
|
||||||
/* The +1 in the number of bytes to be moved is caused by the
|
|
||||||
* end-of-zipmap byte. Note: the *original* zmlen is used. */
|
|
||||||
memmove(p + reqlen, p + freelen, zmlen - (offset + freelen + 1));
|
|
||||||
zmlen = zmlen - freelen + reqlen;
|
|
||||||
freelen = reqlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We now have a suitable block where the key/value entry can
|
|
||||||
* be written. If there is too much free space, move the tail
|
|
||||||
* of the zipmap a few bytes to the front and shrink the zipmap,
|
|
||||||
* as we want zipmaps to be very space efficient. */
|
|
||||||
empty = freelen - reqlen;
|
|
||||||
if (empty >= ZIPMAP_VALUE_MAX_FREE) {
|
|
||||||
/* First, move the tail <empty> bytes to the front, then resize
|
|
||||||
* the zipmap to be <empty> bytes smaller. */
|
|
||||||
offset = p - zm;
|
|
||||||
memmove(p + reqlen, p + freelen, zmlen - (offset + freelen + 1));
|
|
||||||
zmlen -= empty;
|
|
||||||
zm = zipmapResize(zm, zmlen);
|
|
||||||
p = zm + offset;
|
|
||||||
vempty = 0;
|
|
||||||
} else {
|
|
||||||
vempty = empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Just write the key + value and we are done. */
|
|
||||||
/* Key: */
|
|
||||||
p += zipmapEncodeLength(p, klen);
|
|
||||||
memcpy(p, key, klen);
|
|
||||||
p += klen;
|
|
||||||
/* Value: */
|
|
||||||
p += zipmapEncodeLength(p, vlen);
|
|
||||||
*p++ = vempty;
|
|
||||||
memcpy(p, val, vlen);
|
|
||||||
return zm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the specified key. If 'deleted' is not NULL the pointed integer is
|
|
||||||
* set to 0 if the key was not found, to 1 if it was found and deleted. */
|
|
||||||
unsigned char *zipmapDel(unsigned char *zm, unsigned char *key, unsigned int klen, int *deleted) {
|
|
||||||
unsigned int zmlen, freelen;
|
|
||||||
unsigned char *p = zipmapLookupRaw(zm, key, klen, &zmlen);
|
|
||||||
if (p) {
|
|
||||||
freelen = zipmapRawEntryLength(p);
|
|
||||||
memmove(p, p + freelen, zmlen - ((p - zm) + freelen + 1));
|
|
||||||
zm = zipmapResize(zm, zmlen - freelen);
|
|
||||||
|
|
||||||
/* Decrease zipmap length */
|
|
||||||
if (zm[0] < ZIPMAP_BIGLEN) zm[0]--;
|
|
||||||
|
|
||||||
if (deleted) *deleted = 1;
|
|
||||||
} else {
|
|
||||||
if (deleted) *deleted = 0;
|
|
||||||
}
|
|
||||||
return zm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call before iterating through elements via zipmapNext() */
|
/* Call before iterating through elements via zipmapNext() */
|
||||||
unsigned char *zipmapRewind(unsigned char *zm) {
|
unsigned char *zipmapRewind(unsigned char *zm) {
|
||||||
return zm + 1;
|
return zm + 1;
|
||||||
@ -335,47 +171,6 @@ zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned
|
|||||||
return zm;
|
return zm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search a key and retrieve the pointer and len of the associated value.
|
|
||||||
* If the key is found the function returns 1, otherwise 0. */
|
|
||||||
int zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen) {
|
|
||||||
unsigned char *p;
|
|
||||||
|
|
||||||
if ((p = zipmapLookupRaw(zm, key, klen, NULL)) == NULL) return 0;
|
|
||||||
p += zipmapRawKeyLength(p);
|
|
||||||
*vlen = zipmapDecodeLength(p);
|
|
||||||
*value = p + ZIPMAP_LEN_BYTES(*vlen) + 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return 1 if the key exists, otherwise 0 is returned. */
|
|
||||||
int zipmapExists(unsigned char *zm, unsigned char *key, unsigned int klen) {
|
|
||||||
return zipmapLookupRaw(zm, key, klen, NULL) != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the number of entries inside a zipmap */
|
|
||||||
unsigned int zipmapLen(unsigned char *zm) {
|
|
||||||
unsigned int len = 0;
|
|
||||||
if (zm[0] < ZIPMAP_BIGLEN) {
|
|
||||||
len = zm[0];
|
|
||||||
} else {
|
|
||||||
unsigned char *p = zipmapRewind(zm);
|
|
||||||
while ((p = zipmapNext(p, NULL, NULL, NULL, NULL)) != NULL) len++;
|
|
||||||
|
|
||||||
/* Re-store length if small enough */
|
|
||||||
if (len < ZIPMAP_BIGLEN) zm[0] = len;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the raw size in bytes of a zipmap, so that we can serialize
|
|
||||||
* the zipmap on disk (or everywhere is needed) just writing the returned
|
|
||||||
* amount of bytes of the C array starting at the zipmap pointer. */
|
|
||||||
size_t zipmapBlobLen(unsigned char *zm) {
|
|
||||||
unsigned int totlen;
|
|
||||||
zipmapLookupRaw(zm, NULL, 0, &totlen);
|
|
||||||
return totlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate the integrity of the data structure.
|
/* Validate the integrity of the data structure.
|
||||||
* when `deep` is 0, only the integrity of the header is validated.
|
* when `deep` is 0, only the integrity of the header is validated.
|
||||||
* when `deep` is 1, we scan all the entries one by one. */
|
* when `deep` is 1, we scan all the entries one by one. */
|
||||||
|
@ -35,17 +35,9 @@
|
|||||||
#ifndef _ZIPMAP_H
|
#ifndef _ZIPMAP_H
|
||||||
#define _ZIPMAP_H
|
#define _ZIPMAP_H
|
||||||
|
|
||||||
unsigned char *zipmapNew(void);
|
|
||||||
unsigned char *
|
|
||||||
zipmapSet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char *val, unsigned int vlen, int *update);
|
|
||||||
unsigned char *zipmapDel(unsigned char *zm, unsigned char *key, unsigned int klen, int *deleted);
|
|
||||||
unsigned char *zipmapRewind(unsigned char *zm);
|
unsigned char *zipmapRewind(unsigned char *zm);
|
||||||
unsigned char *
|
unsigned char *
|
||||||
zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen);
|
zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen);
|
||||||
int zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen);
|
|
||||||
int zipmapExists(unsigned char *zm, unsigned char *key, unsigned int klen);
|
|
||||||
unsigned int zipmapLen(unsigned char *zm);
|
|
||||||
size_t zipmapBlobLen(unsigned char *zm);
|
|
||||||
int zipmapValidateIntegrity(unsigned char *zm, size_t size, int deep);
|
int zipmapValidateIntegrity(unsigned char *zm, size_t size, int deep);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user