Finish working phonebook.
This commit is contained in:
parent
82f5e32ddb
commit
0d28baef0e
143
Arena.cc
143
Arena.cc
|
@ -10,40 +10,56 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(DESKTOP_BUILD)
|
||||||
|
#include <iostream>
|
||||||
|
#include <ios>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "Arena.h"
|
#include "Arena.h"
|
||||||
|
|
||||||
|
|
||||||
#define ARENA_UNINIT 0
|
#define ARENA_UNINIT 0
|
||||||
#define ARENA_STATIC 1
|
#define ARENA_STATIC 1
|
||||||
#define ARENA_ALLOC 2
|
#define ARENA_ALLOC 2
|
||||||
|
#if defined(__linux__)
|
||||||
#define ARENA_MMAP 3
|
#define ARENA_MMAP 3
|
||||||
|
|
||||||
#define PROT_RW PROT_READ|PROT_WRITE
|
#define PROT_RW PROT_READ|PROT_WRITE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
InitializeArena(Arena &arena)
|
||||||
|
{
|
||||||
|
arena.Store = NULL;
|
||||||
|
arena.Size = 0;
|
||||||
|
arena.Type = ARENA_UNINIT;
|
||||||
|
arena.fd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
new_arena(Arena &arena, uint8_t *mem, size_t size)
|
NewStaticArena(Arena &arena, uint8_t *mem, size_t size)
|
||||||
{
|
{
|
||||||
arena.store = mem;
|
arena.Store = mem;
|
||||||
arena.size = size;
|
arena.Size = size;
|
||||||
arena.type = ARENA_STATIC;
|
arena.Type = ARENA_STATIC;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
alloc_new_arena(Arena &arena, size_t size)
|
AllocNewArena(Arena & arena, size_t size)
|
||||||
{
|
{
|
||||||
if (arena.size > 0) {
|
if (arena.Size > 0) {
|
||||||
if (arena_destroy(arena) != 0) {
|
if (DestroyArena(arena) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arena.type = ARENA_ALLOC;
|
arena.Type = ARENA_ALLOC;
|
||||||
arena.size = size;
|
arena.Size = size;
|
||||||
arena.store = (uint8_t *)calloc(sizeof(uint8_t), size);
|
arena.Store = (uint8_t *)calloc(sizeof(uint8_t), size);
|
||||||
if (arena.store == NULL) {
|
if (arena.Store == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,17 +69,17 @@ alloc_new_arena(Arena &arena, size_t size)
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
int
|
int
|
||||||
mmap_arena(Arena &arena, int fd, size_t size)
|
MMapArena(Arena &arena, int fd, size_t Size)
|
||||||
{
|
{
|
||||||
if (arena.size > 0) {
|
if (arena.Size > 0) {
|
||||||
if (arena_destroy(arena) != 0) {
|
if (arena_destroy(arena) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arena.type = ARENA_MMAP;
|
arena.Type = ARENA_MMAP;
|
||||||
arena.size = size;
|
arena.Size = Size;
|
||||||
arena.store = (uint8_t *)mmap(NULL, size, PROT_RW, MAP_SHARED, fd, 0);
|
arena.store = (uint8_t *)mmap(NULL, Size, PROT_RW, MAP_SHARED, fd, 0);
|
||||||
if ((void *)arena.store == MAP_FAILED) {
|
if ((void *)arena.store == MAP_FAILED) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -73,11 +89,11 @@ mmap_arena(Arena &arena, int fd, size_t size)
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
open_arena(Arena &arena, const char *path)
|
OpenArena(Arena &arena, const char *path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (arena.size > 0) {
|
if (arena.Size > 0) {
|
||||||
if (arena_destroy(arena) != 0) {
|
if (arena_destroy(arena) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -92,16 +108,16 @@ open_arena(Arena &arena, const char *path)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mmap_arena(arena, arena.fd, (size_t)st.st_size);
|
return MMapArena(arena, arena.fd, (size_t)st.st_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
create_arena(Arena &arena, const char *path, size_t size, mode_t mode)
|
CreateArena(Arena &arena, const char *path, size_t Size, mode_t mode)
|
||||||
{
|
{
|
||||||
int fd = 0;
|
int fd = 0;
|
||||||
|
|
||||||
if (arena.size > 0) {
|
if (arena.Size > 0) {
|
||||||
if (arena_destroy(arena) != 0) {
|
if (arena_destroy(arena) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -112,43 +128,49 @@ create_arena(Arena &arena, const char *path, size_t size, mode_t mode)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ftruncate(fd, size) == -1) {
|
if (ftruncate(fd, Size) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
return open_arena(arena, path);
|
return OpenArena(arena, path);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ClearArena clears the memory being used, removing any data
|
||||||
|
* present. It does not free the memory; it is effectively a
|
||||||
|
* wrapper around memset.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
arena_clear(Arena &arena)
|
ClearArena(Arena &arena)
|
||||||
{
|
{
|
||||||
if (arena.size == 0) {
|
if (arena.Size == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(arena.store, 0, arena.size);
|
memset(arena.Store, 0, arena.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
arena_destroy(Arena &arena)
|
DestroyArena(Arena &arena)
|
||||||
{
|
{
|
||||||
if (arena.type == ARENA_UNINIT) {
|
if (arena.Type == ARENA_UNINIT) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (arena.type) {
|
switch (arena.Type) {
|
||||||
case ARENA_STATIC:
|
case ARENA_STATIC:
|
||||||
break;
|
break;
|
||||||
case ARENA_ALLOC:
|
case ARENA_ALLOC:
|
||||||
free(arena.store);
|
free(arena.Store);
|
||||||
break;
|
break;
|
||||||
|
#if defined(__linux__)
|
||||||
case ARENA_MMAP:
|
case ARENA_MMAP:
|
||||||
if (munmap(arena.store, arena.size) == -1) {
|
if (munmap(arena.store, arena.Size) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,20 +180,63 @@ arena_destroy(Arena &arena)
|
||||||
|
|
||||||
arena.fd = 0;
|
arena.fd = 0;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
abort();
|
#if defined(NDEBUG)
|
||||||
return -1;
|
return -1;
|
||||||
|
#else
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
arena.type = ARENA_UNINIT;
|
arena.Type = ARENA_UNINIT;
|
||||||
arena.size = 0;
|
arena.Size = 0;
|
||||||
arena.store = NULL;
|
arena.Store = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(DESKTOP_BUILD)
|
||||||
|
void
|
||||||
|
DisplayArena(const Arena &arena)
|
||||||
|
{
|
||||||
|
std::cout << "Arena @ 0x";
|
||||||
|
std::cout << std::hex << (uintptr_t)&arena << std::endl;
|
||||||
|
std::cout << std::dec;
|
||||||
|
std::cout << "\tStore is " << arena.Size << " bytes at address 0x";
|
||||||
|
std::cout << std::hex << (uintptr_t)&(arena.Store) << std::endl;
|
||||||
|
std::cout << "\tType: ";
|
||||||
|
|
||||||
|
switch (arena.Type) {
|
||||||
|
case ARENA_UNINIT:
|
||||||
|
std::cout << "uninitialized";
|
||||||
|
break;
|
||||||
|
case ARENA_STATIC:
|
||||||
|
std::cout << "static";
|
||||||
|
break;
|
||||||
|
case ARENA_ALLOC:
|
||||||
|
std::cout << "allocated";
|
||||||
|
break;
|
||||||
|
#if defined(__linux__)
|
||||||
|
case ARENA_MMAP:
|
||||||
|
std::cout << "mmap/file"
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
std::cout << "unknown (this is a bug)";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
DisplayArena(const Arena &arena)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
write_arena(Arena &arena, const char *path)
|
WriteArena(const Arena &arena, const char *path)
|
||||||
{
|
{
|
||||||
FILE *arenaFile = NULL;
|
FILE *arenaFile = NULL;
|
||||||
int retc = -1;
|
int retc = -1;
|
||||||
|
@ -181,8 +246,8 @@ write_arena(Arena &arena, const char *path)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fwrite(arena.store, sizeof(*arena.store), arena.size,
|
if (fwrite(arena.Store, sizeof(*arena.Store), arena.Size,
|
||||||
arenaFile) == arena.size) {
|
arenaFile) == arena.Size) {
|
||||||
retc = 0;
|
retc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
33
Arena.h
33
Arena.h
|
@ -8,27 +8,38 @@
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t *store;
|
uint8_t *Store;
|
||||||
size_t size;
|
size_t Size;
|
||||||
int fd;
|
int fd;
|
||||||
uint8_t type;
|
uint8_t Type;
|
||||||
} Arena;
|
} Arena;
|
||||||
|
|
||||||
|
|
||||||
int new_arena(Arena &, uint8_t *, size_t);
|
/*
|
||||||
int alloc_new_arena(Arena &, size_t);
|
* InitializeArena is intended for use only with systems that
|
||||||
|
* do not initialize new variables to zero. It should be called
|
||||||
|
* exactly once, at the start of the program. Any other time the
|
||||||
|
* arena needs to be reset, it should be called with clear_arena
|
||||||
|
* or destroy_arena.
|
||||||
|
*/
|
||||||
|
void InitializeArena(Arena &arena);
|
||||||
|
int NewStaticArena(Arena &, uint8_t *, size_t);
|
||||||
|
int AllocNewArena(Arena &, size_t);
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
int mmap_arena(Arena &, int); /* arena will own fd */
|
int MMapArena(Arena &, int); /* arena will own fd */
|
||||||
int create_arena(Arena &arena, const char *path, size_t size, mode_t mode);
|
int CreateArena(Arena &arena, const char *path, size_t size, mode_t mode);
|
||||||
int open_arena(Arena &, const char *, size_t);
|
int OpenArena(Arena &, const char *, size_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void arena_clear(Arena &);
|
void ClearArena(Arena &);
|
||||||
int arena_destroy(Arena &); /* dispose of any memory used by arena */
|
int DestroyArena(Arena &); /* dispose of any memory used by arena */
|
||||||
|
|
||||||
/* DANGER: if arena is file backed (mmap or open), DO NOT WRITE TO THE
|
/* DANGER: if arena is file backed (mmap or open), DO NOT WRITE TO THE
|
||||||
* BACKING FILE! */
|
* BACKING FILE! */
|
||||||
int write_arena(const char *);
|
int WriteArena(const Arena &arena, const char *path);
|
||||||
|
|
||||||
|
void
|
||||||
|
DisplayArena(const Arena &arena);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,10 +2,26 @@ cmake_minimum_required(VERSION 3.25)
|
||||||
project(klib CXX)
|
project(klib CXX)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
if(MSVC)
|
||||||
|
add_compile_options("/W4" "$<$<CONFIG:RELEASE>:/O2>")
|
||||||
|
else()
|
||||||
|
add_compile_options("-Wall" "-Wextra" "-Werror" "$<$<CONFIG:RELEASE>:-O3>")
|
||||||
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
|
add_compile_options("-stdlib=libc++")
|
||||||
|
else()
|
||||||
|
# nothing special for gcc at the moment
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
add_compile_options("-DDESKTOP_BUILD")
|
||||||
|
|
||||||
add_library(klib STATIC
|
add_library(klib STATIC
|
||||||
Arena.cc
|
Arena.cc
|
||||||
TLV.cc)
|
TLV.cc
|
||||||
|
Phonebook.cc)
|
||||||
|
|
||||||
add_executable(tlv_test tlv_test.cc)
|
add_executable(tlv_test tlv_test.cc)
|
||||||
target_link_libraries(tlv_test klib)
|
target_link_libraries(tlv_test klib)
|
||||||
|
|
||||||
|
add_executable(phonebook_test phonebook_test.cc)
|
||||||
|
target_link_libraries(phonebook_test klib)
|
||||||
|
|
||||||
|
|
101
Phonebook.cc
101
Phonebook.cc
|
@ -2,22 +2,26 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include "Phonebook.h"
|
#include "Phonebook.h"
|
||||||
|
|
||||||
|
#if defined(DESKTOP_BUILD)
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Phonebook::lookup(const char *key, uint8_t klen, TLV::Record &res)
|
Phonebook::Lookup(const char *key, uint8_t klen, TLV::Record &res)
|
||||||
{
|
{
|
||||||
res.Tag = this->ktag;
|
res.Tag = this->kTag;
|
||||||
uint8_t *cursor = TLV::find_tag(this->arena, NULL, res);
|
uint8_t *cursor = TLV::FindTag(this->arena, NULL, res);
|
||||||
|
|
||||||
while (cursor != NULL) {
|
while (cursor != NULL) {
|
||||||
if ((klen == res.Len) &&
|
if ((klen == res.Len) &&
|
||||||
(memcmp(res.Val, key, klen) == 0)) {
|
(memcmp(res.Val, key, klen) == 0)) {
|
||||||
TLV::read_from_memory(res, cursor);
|
TLV::ReadFromMemory(res, cursor);
|
||||||
if (res.Tag != this->vtag) {
|
if (res.Tag != this->vTag) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
cursor = TLV::find_tag(this->arena, cursor, res);
|
cursor = TLV::FindTag(this->arena, cursor, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -26,29 +30,29 @@ Phonebook::lookup(const char *key, uint8_t klen, TLV::Record &res)
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Phonebook::set(const char *key, uint8_t klen, const char *val, uint8_t vlen)
|
Phonebook::Set(const char *key, uint8_t klen, const char *val, uint8_t vlen)
|
||||||
{
|
{
|
||||||
TLV::Record rec;
|
TLV::Record rec;
|
||||||
uint8_t *cursor = NULL;
|
uint8_t *cursor = NULL;
|
||||||
|
|
||||||
set_record(rec, this->ktag, klen, key);
|
SetRecord(rec, this->kTag, klen, key);
|
||||||
cursor = this->seek(key, klen);
|
cursor = this->seek(key, klen);
|
||||||
if (cursor != NULL) {
|
if (cursor != NULL) {
|
||||||
TLV::delete_record(this->arena, cursor);
|
TLV::DeleteRecord(this->arena, cursor);
|
||||||
TLV::delete_record(this->arena, cursor);
|
TLV::DeleteRecord(this->arena, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!space_available(klen, vlen)) {
|
if (!spaceAvailable(klen, vlen)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = TLV::write_to_memory(this->arena, NULL, rec);
|
cursor = TLV::WriteToMemory(this->arena, NULL, rec);
|
||||||
if (cursor == NULL) {
|
if (cursor == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_record(rec, this->vtag, vlen, val);
|
SetRecord(rec, this->vTag, vlen, val);
|
||||||
if (TLV::write_to_memory(this->arena, NULL, rec) == NULL) {
|
if (TLV::WriteToMemory(this->arena, NULL, rec) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,15 +66,17 @@ Phonebook::seek(const char *key, uint8_t klen)
|
||||||
{
|
{
|
||||||
TLV::Record rec;
|
TLV::Record rec;
|
||||||
|
|
||||||
rec.Tag = this->ktag;
|
rec.Tag = this->kTag;
|
||||||
uint8_t *cursor = TLV::find_tag(this->arena, NULL, rec);
|
uint8_t *cursor = TLV::LocateTag(this->arena, NULL, rec);
|
||||||
|
|
||||||
while (cursor != NULL) {
|
while (cursor != NULL) {
|
||||||
if ((klen == rec.Len) &&
|
if ((klen == rec.Len) && (this->kTag == rec.Tag)) {
|
||||||
(memcmp(rec.Val, key, klen) == 0)) {
|
if (memcmp(rec.Val, key, klen) == 0) {
|
||||||
return cursor;
|
return cursor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cursor = TLV::skip_record(rec, cursor);
|
cursor = TLV::SkipRecord(rec, cursor);
|
||||||
|
cursor = TLV::LocateTag(this->arena, cursor, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -78,29 +84,68 @@ Phonebook::seek(const char *key, uint8_t klen)
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Phonebook::has(const char *key, uint8_t klen)
|
Phonebook::Has(const char *key, uint8_t klen)
|
||||||
{
|
{
|
||||||
return this->seek(key, klen) != NULL;
|
return this->seek(key, klen) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Phonebook::space_available(uint8_t kl, uint8_t vl)
|
Phonebook::spaceAvailable(uint8_t klen, uint8_t vlen)
|
||||||
{
|
{
|
||||||
size_t required = 0;
|
size_t required = 0;
|
||||||
uintptr_t remaining = 0;
|
uintptr_t remaining = 0;
|
||||||
uint8_t *cursor = NULL;
|
uint8_t *cursor = NULL;
|
||||||
|
|
||||||
|
cursor = TLV::FindEmpty(this->arena, NULL);
|
||||||
cursor = TLV::find_empty(this->arena, NULL);
|
|
||||||
if (cursor == NULL) {
|
if (cursor == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
required += kl + 2;
|
required += klen + 2;
|
||||||
required += vl + 2;
|
required += vlen + 2;
|
||||||
|
|
||||||
remaining = (uintptr_t)cursor - (uintptr_t)arena.store;
|
remaining = (uintptr_t)cursor - (uintptr_t)arena.Store;
|
||||||
remaining = arena.size - remaining;
|
remaining = arena.Size - remaining;
|
||||||
return ((size_t)remaining >= required);
|
return ((size_t)remaining >= required);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DESKTOP_BUILD)
|
||||||
|
void
|
||||||
|
Phonebook::DumpKVPairs()
|
||||||
|
{
|
||||||
|
uint8_t *cursor = (this->arena).Store;
|
||||||
|
TLV::Record rec;
|
||||||
|
|
||||||
|
TLV::ReadFromMemory(rec, cursor);
|
||||||
|
std::cout << "Phonebook KV pairs" << std::endl;
|
||||||
|
if (rec.Tag == TAG_EMPTY) {
|
||||||
|
std::cout << "\t(NONE)" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((cursor != NULL) && (rec.Tag != TAG_EMPTY)) {
|
||||||
|
std::cout << "\t" << rec.Val << "->";
|
||||||
|
cursor = TLV::SkipRecord(rec, cursor);
|
||||||
|
TLV::ReadFromMemory(rec, cursor);
|
||||||
|
std::cout << rec.Val << std::endl;
|
||||||
|
cursor = TLV::SkipRecord(rec, cursor);
|
||||||
|
TLV::ReadFromMemory(rec, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Phonebook::DumpToFile(const char *path)
|
||||||
|
{
|
||||||
|
WriteArena(this->arena, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
Phonebook::dump_kvpairs()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
29
Phonebook.h
29
Phonebook.h
|
@ -14,26 +14,27 @@
|
||||||
class Phonebook {
|
class Phonebook {
|
||||||
public:
|
public:
|
||||||
Phonebook(Arena &arena) :
|
Phonebook(Arena &arena) :
|
||||||
arena(arena),
|
arena(arena),
|
||||||
ktag(PHONEBOOK_KEY_TAG),
|
kTag(PHONEBOOK_KEY_TAG),
|
||||||
vtag(PHONEBOOK_VAL_TAG) {} ;
|
vTag(PHONEBOOK_VAL_TAG) {} ;
|
||||||
Phonebook(Arena &arena, uint8_t kt, uint8_t vt) :
|
Phonebook(Arena &arena, uint8_t kt, uint8_t vt) :
|
||||||
arena(arena),
|
arena(arena),
|
||||||
ktag(kt),
|
kTag(kt),
|
||||||
vtag(vt) {};
|
vTag(vt) {};
|
||||||
|
|
||||||
bool lookup(const char *key, uint8_t klen, TLV::Record &res);
|
|
||||||
int set(const char *key, uint8_t klen, const char *val,
|
|
||||||
uint8_t vlen);
|
|
||||||
bool has(const char *key, uint8_t klen);
|
|
||||||
|
|
||||||
|
bool Lookup(const char *key, uint8_t klen, TLV::Record &res);
|
||||||
|
int Set(const char *key, uint8_t klen, const char *val,
|
||||||
|
uint8_t vlen);
|
||||||
|
bool Has(const char *key, uint8_t klen);
|
||||||
|
void DumpKVPairs();
|
||||||
|
void DumpToFile(const char *path);
|
||||||
private:
|
private:
|
||||||
uint8_t *seek(const char *key, uint8_t klen);
|
uint8_t *seek(const char *key, uint8_t klen);
|
||||||
bool space_available(uint8_t klen, uint8_t vlen);
|
bool spaceAvailable(uint8_t klen, uint8_t vlen);
|
||||||
|
|
||||||
Arena &arena;
|
Arena &arena;
|
||||||
uint8_t ktag;
|
uint8_t kTag;
|
||||||
uint8_t vtag;
|
uint8_t vTag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
67
TLV.cc
67
TLV.cc
|
@ -9,7 +9,7 @@ namespace TLV {
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
space_available(Arena &arena, uint8_t *cursor, uint8_t len)
|
spaceAvailable(Arena &arena, uint8_t *cursor, uint8_t len)
|
||||||
{
|
{
|
||||||
uintptr_t remaining = 0;
|
uintptr_t remaining = 0;
|
||||||
|
|
||||||
|
@ -17,76 +17,95 @@ space_available(Arena &arena, uint8_t *cursor, uint8_t len)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
remaining = (uintptr_t)cursor - (uintptr_t)arena.store;
|
remaining = (uintptr_t)cursor - (uintptr_t)arena.Store;
|
||||||
remaining = arena.size - remaining;
|
remaining = arena.Size - remaining;
|
||||||
return ((size_t)remaining >= ((size_t)len+2));
|
return ((size_t)remaining >= ((size_t)len+2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
clearUnused(Record &rec)
|
||||||
|
{
|
||||||
|
uint8_t trail = TLV_MAX_LEN-rec.Len;
|
||||||
|
|
||||||
|
memset(rec.Val+rec.Len, 0, trail);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t *
|
uint8_t *
|
||||||
write_to_memory(Arena &arena, uint8_t *cursor, Record &rec)
|
WriteToMemory(Arena &arena, uint8_t *cursor, Record &rec)
|
||||||
{
|
{
|
||||||
// If cursor is NULL, the user needs us to select an empty
|
// If cursor is NULL, the user needs us to select an empty
|
||||||
// slot for the record. If we can't find one, that's an
|
// slot for the record. If we can't find one, that's an
|
||||||
// error.
|
// error.
|
||||||
//
|
//
|
||||||
// If, however, the user gives us a cursor, we'll trust it
|
// If, however, the user gives us a cursor, we'll trust it
|
||||||
// (though space_available will sanity check that cursor).
|
// (though spaceAvailable will sanity check that cursor).
|
||||||
if (cursor == NULL) {
|
if (cursor == NULL) {
|
||||||
cursor = find_empty(arena, cursor);
|
cursor = FindEmpty(arena, cursor);
|
||||||
if (cursor == NULL) {
|
if (cursor == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!space_available(arena, cursor, rec.Len)) {
|
if (!spaceAvailable(arena, cursor, rec.Len)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(cursor, &rec, REC_SIZE(rec));
|
memcpy(cursor, &rec, REC_SIZE(rec));
|
||||||
cursor = skip_record(rec, cursor);
|
cursor = SkipRecord(rec, cursor);
|
||||||
|
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
set_record(Record &rec, uint8_t tag, uint8_t len, const char *val)
|
SetRecord(Record &rec, uint8_t tag, uint8_t len, const char *val)
|
||||||
{
|
{
|
||||||
uint8_t trail = TLV_MAX_LEN-len;
|
|
||||||
|
|
||||||
rec.Tag = tag;
|
rec.Tag = tag;
|
||||||
rec.Len = len;
|
rec.Len = len;
|
||||||
memcpy(rec.Val, val, len);
|
memcpy(rec.Val, val, len);
|
||||||
memset(rec.Val+len, 0, trail);
|
clearUnused(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
read_from_memory(Record &rec, uint8_t *cursor)
|
ReadFromMemory(Record &rec, uint8_t *cursor)
|
||||||
{
|
{
|
||||||
rec.Tag = cursor[0];
|
rec.Tag = cursor[0];
|
||||||
rec.Len = cursor[1];
|
rec.Len = cursor[1];
|
||||||
memcpy(rec.Val, cursor+2, rec.Len);
|
memcpy(rec.Val, cursor+2, rec.Len);
|
||||||
|
clearUnused(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns a pointer to memory where the record was found,
|
* returns a pointer to memory where the record was found,
|
||||||
* e.g. find_tag(...)[0] is the tag of the found record.
|
* e.g. FindTag(...)[0] is the tag of the found record.
|
||||||
*/
|
*/
|
||||||
uint8_t *
|
uint8_t *
|
||||||
find_tag(Arena &arena, uint8_t *cursor, Record &rec)
|
FindTag(Arena &arena, uint8_t *cursor, Record &rec)
|
||||||
|
{
|
||||||
|
cursor = LocateTag(arena, cursor, rec);
|
||||||
|
if (rec.Tag != TAG_EMPTY) {
|
||||||
|
cursor = SkipRecord(rec, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t *
|
||||||
|
LocateTag(Arena &arena, uint8_t *cursor, Record &rec)
|
||||||
{
|
{
|
||||||
uint8_t tag, len;
|
uint8_t tag, len;
|
||||||
|
|
||||||
if (cursor == NULL) {
|
if (cursor == NULL) {
|
||||||
cursor = arena.store;
|
cursor = arena.Store;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((tag = cursor[0]) != rec.Tag) {
|
while ((tag = cursor[0]) != rec.Tag) {
|
||||||
len = cursor[1];
|
len = cursor[1];
|
||||||
if (!space_available(arena, cursor, len)) {
|
if (!spaceAvailable(arena, cursor, len)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
cursor += len;
|
cursor += len;
|
||||||
|
@ -98,40 +117,38 @@ find_tag(Arena &arena, uint8_t *cursor, Record &rec)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag != TAG_EMPTY) {
|
if (tag != TAG_EMPTY) {
|
||||||
read_from_memory(rec, cursor);
|
ReadFromMemory(rec, cursor);
|
||||||
cursor = skip_record(rec, cursor);
|
|
||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t *
|
uint8_t *
|
||||||
find_empty(Arena &arena, uint8_t *cursor) {
|
FindEmpty(Arena &arena, uint8_t *cursor) {
|
||||||
Record rec;
|
Record rec;
|
||||||
|
|
||||||
rec.Tag = TAG_EMPTY;
|
rec.Tag = TAG_EMPTY;
|
||||||
return find_tag(arena, cursor, rec);
|
return FindTag(arena, cursor, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t *
|
uint8_t *
|
||||||
skip_record(Record &rec, uint8_t *cursor)
|
SkipRecord(Record &rec, uint8_t *cursor)
|
||||||
{
|
{
|
||||||
return (uint8_t *)((uintptr_t)cursor + rec.Len + 2);
|
return (uint8_t *)((uintptr_t)cursor + rec.Len + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
delete_record(Arena &arena, uint8_t *cursor)
|
DeleteRecord(Arena &arena, uint8_t *cursor)
|
||||||
{
|
{
|
||||||
//
|
|
||||||
if (cursor == NULL) {
|
if (cursor == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t len = cursor[1] + 2;
|
uint8_t len = cursor[1] + 2;
|
||||||
uint8_t *stop = arena.store + arena.size;
|
uint8_t *stop = arena.Store + arena.Size;
|
||||||
|
|
||||||
stop -= len;
|
stop -= len;
|
||||||
|
|
||||||
|
|
22
TLV.h
22
TLV.h
|
@ -24,18 +24,22 @@ struct Record {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
uint8_t *write_to_memory(Arena &, uint8_t *, Record &);
|
uint8_t *WriteToMemory(Arena &, uint8_t *, Record &);
|
||||||
void read_from_memory(Record &, uint8_t *);
|
void ReadFromMemory(Record &, uint8_t *);
|
||||||
void set_record(Record &, uint8_t, uint8_t, const char *);
|
void SetRecord(Record &, uint8_t, uint8_t, const char *);
|
||||||
void delete_record(Arena &, uint8_t *);
|
void DeleteRecord(Arena &, uint8_t *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns a pointer to memory where the record was found,
|
* returns a pointer to memory where the record was found,
|
||||||
* e.g. find_tag(...)[0] is the tag of the found record.
|
* e.g. LocateTag(...)[0] is the tag of the found record.
|
||||||
|
* FindTag will call LocateTag and then SkipRecord if the
|
||||||
|
* tag was found.
|
||||||
*/
|
*/
|
||||||
uint8_t *find_tag(Arena &, uint8_t *, Record &);
|
uint8_t *FindTag(Arena &, uint8_t *, Record &);
|
||||||
uint8_t *find_empty(Arena &, uint8_t *);
|
uint8_t *LocateTag(Arena &, uint8_t *, Record &);
|
||||||
uint8_t *skip_record(Record &, uint8_t *);
|
|
||||||
|
uint8_t *FindEmpty(Arena &, uint8_t *);
|
||||||
|
uint8_t *SkipRecord(Record &, uint8_t *);
|
||||||
|
|
||||||
|
|
||||||
} // namespace TLV
|
} // namespace TLV
|
||||||
|
|
|
@ -12,14 +12,12 @@ constexpr char TEST_PBSTR2[] = "baz";
|
||||||
constexpr uint8_t TEST_PBSTRLEN2 = 3;
|
constexpr uint8_t TEST_PBSTRLEN2 = 3;
|
||||||
constexpr char TEST_PBSTR3[] = "quux";
|
constexpr char TEST_PBSTR3[] = "quux";
|
||||||
constexpr uint8_t TEST_PBSTRLEN3 = 4;
|
constexpr uint8_t TEST_PBSTRLEN3 = 4;
|
||||||
/*
|
|
||||||
constexpr char TEST_PBSTR4[] = "spam";
|
constexpr char TEST_PBSTR4[] = "spam";
|
||||||
constexpr uint8_t TEST_PBSTRLEN4 = 4;
|
constexpr uint8_t TEST_PBSTRLEN4 = 4;
|
||||||
constexpr char TEST_PBSTR5[] = "xyzzx";
|
constexpr char TEST_PBSTR5[] = "xyzzx";
|
||||||
constexpr uint8_t TEST_PBSTRLEN5 = 5;
|
constexpr uint8_t TEST_PBSTRLEN5 = 5;
|
||||||
constexpr char TEST_PBSTR6[] = "corvid";
|
constexpr char TEST_PBSTR6[] = "corvid";
|
||||||
constexpr uint8_t TEST_PBSTRLEN6 = 6;
|
constexpr uint8_t TEST_PBSTRLEN6 = 6;
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -27,9 +25,9 @@ test_setpb(Phonebook &pb, const char *k, uint8_t kl, const char *v,
|
||||||
uint8_t vl)
|
uint8_t vl)
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
std::cout << "test set " << k << "->" << v << std::endl;
|
std::cout << "test Set " << k << "->" << v << std::endl;
|
||||||
ok = pb.set(k, kl, v, vl) == 0;
|
ok = pb.Set(k, kl, v, vl) == 0;
|
||||||
std::cout << "\tset complete\n";
|
std::cout << "\tSet complete\n";
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,21 +36,69 @@ int
|
||||||
main(int argc, const char *argv[])
|
main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
Arena arena;
|
Arena arena;
|
||||||
//TLV::Record value;
|
TLV::Record value;
|
||||||
//TLV::Record expect;
|
TLV::Record expect;
|
||||||
|
|
||||||
std::cout << "TESTPROG: " << argv[0] << std::endl;
|
std::cout << "TESTPROG: " << argv[0] << std::endl;
|
||||||
if (create_arena(arena, ARENA_FILE, ARENA_SIZE, 0644) == -1) {
|
InitializeArena(arena);
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
if (CreateArena(arena, ARENA_FILE, ARENA_SIZE, 0644) == -1) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (AllocNewArena(arena, ARENA_SIZE) == -1) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
DisplayArena(arena);
|
||||||
|
|
||||||
|
TLV::SetRecord(expect, PHONEBOOK_VAL_TAG, TEST_PBSTRLEN3, TEST_PBSTR3);
|
||||||
|
|
||||||
Phonebook pb(arena);
|
Phonebook pb(arena);
|
||||||
assert(!pb.has(TEST_PBSTR2, TEST_PBSTRLEN2));
|
assert(!pb.Has(TEST_PBSTR2, TEST_PBSTRLEN2));
|
||||||
|
|
||||||
assert(test_setpb(pb, TEST_PBSTR1, TEST_PBSTRLEN1, TEST_PBSTR3,
|
assert(test_setpb(pb, TEST_PBSTR1, TEST_PBSTRLEN1, TEST_PBSTR3,
|
||||||
TEST_PBSTRLEN3));
|
TEST_PBSTRLEN3));
|
||||||
|
pb.DumpKVPairs();
|
||||||
assert(test_setpb(pb, TEST_PBSTR2, TEST_PBSTRLEN2, TEST_PBSTR3,
|
assert(test_setpb(pb, TEST_PBSTR2, TEST_PBSTRLEN2, TEST_PBSTR3,
|
||||||
TEST_PBSTRLEN3));
|
TEST_PBSTRLEN3));
|
||||||
|
pb.DumpKVPairs();
|
||||||
|
assert(pb.Has(TEST_PBSTR2, TEST_PBSTRLEN2));
|
||||||
|
assert(test_setpb(pb, TEST_PBSTR4, TEST_PBSTRLEN4, TEST_PBSTR5,
|
||||||
|
TEST_PBSTRLEN5));
|
||||||
|
pb.DumpKVPairs();
|
||||||
|
assert(pb.Lookup(TEST_PBSTR2, TEST_PBSTRLEN2, value));
|
||||||
|
|
||||||
|
assert(cmp_record(value, expect));
|
||||||
|
|
||||||
|
std::cout << "test overwriting key" << std::endl;
|
||||||
|
assert(test_setpb(pb, TEST_PBSTR2, TEST_PBSTRLEN2, TEST_PBSTR6,
|
||||||
|
TEST_PBSTRLEN6));
|
||||||
|
pb.DumpKVPairs();
|
||||||
|
TLV::SetRecord(expect, PHONEBOOK_VAL_TAG, TEST_PBSTRLEN6, TEST_PBSTR6);
|
||||||
|
std::cout << "\tlookup" << std::endl;
|
||||||
|
assert(pb.Lookup(TEST_PBSTR2, TEST_PBSTRLEN2, value));
|
||||||
|
std::cout << "\tcompare records" << std::endl;
|
||||||
|
assert(cmp_record(value, expect));
|
||||||
|
|
||||||
|
std::cout << "\tadd new key to phonebook" << std::endl;
|
||||||
|
assert(test_setpb(pb, TEST_PBSTR3, TEST_PBSTRLEN3, TEST_PBSTR5,
|
||||||
|
TEST_PBSTRLEN5));
|
||||||
|
pb.DumpKVPairs();
|
||||||
|
|
||||||
|
TLV::SetRecord(expect, PHONEBOOK_VAL_TAG, TEST_PBSTRLEN5, TEST_PBSTR5);
|
||||||
|
assert(pb.Lookup(TEST_PBSTR4, TEST_PBSTRLEN4, value));
|
||||||
|
assert(cmp_record(value, expect));
|
||||||
|
|
||||||
std::cout << "OK" <<std::endl;
|
std::cout << "OK" <<std::endl;
|
||||||
|
|
||||||
|
// Dump the generated arena for inspection later.
|
||||||
|
#if defined(__linux__)
|
||||||
|
#else
|
||||||
|
pb.DumpToFile(ARENA_FILE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ClearArena(arena);
|
||||||
|
pb.DumpKVPairs();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,23 @@
|
||||||
#define TEST_STR4 "How is a raven like a writing desk?"
|
#define TEST_STR4 "How is a raven like a writing desk?"
|
||||||
#define TEST_STRLEN4 35
|
#define TEST_STRLEN4 35
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cmp_record(TLV::Record &a, TLV::Record &b)
|
||||||
|
{
|
||||||
|
if (a.Tag != b .Tag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.Len != b.Len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(a.Val, b.Val, a.Len) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
64
tlv_test.cc
64
tlv_test.cc
|
@ -11,60 +11,41 @@
|
||||||
static uint8_t arena_buffer[ARENA_SIZE];
|
static uint8_t arena_buffer[ARENA_SIZE];
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
cmp_record(TLV::Record &a, TLV::Record &b)
|
|
||||||
{
|
|
||||||
if (a.Tag != b .Tag) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a.Len != b.Len) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp(a.Val, b.Val, a.Len) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tlv_test_suite(Arena &backend)
|
tlv_test_suite(Arena &backend)
|
||||||
{
|
{
|
||||||
TLV::Record rec1, rec2, rec3, rec4;
|
TLV::Record rec1, rec2, rec3, rec4;
|
||||||
uint8_t *cursor = NULL;
|
uint8_t *cursor = NULL;
|
||||||
|
|
||||||
TLV::set_record(rec1, 1, TEST_STRLEN1, TEST_STR1);
|
TLV::SetRecord(rec1, 1, TEST_STRLEN1, TEST_STR1);
|
||||||
TLV::set_record(rec2, 2, TEST_STRLEN2, TEST_STR2);
|
TLV::SetRecord(rec2, 2, TEST_STRLEN2, TEST_STR2);
|
||||||
TLV::set_record(rec3, 1, TEST_STRLEN4, TEST_STR4);
|
TLV::SetRecord(rec3, 1, TEST_STRLEN4, TEST_STR4);
|
||||||
rec4.Tag = 1;
|
rec4.Tag = 1;
|
||||||
|
|
||||||
assert(TLV::write_to_memory(backend, cursor, rec1) != NULL);
|
assert(TLV::WriteToMemory(backend, cursor, rec1) != NULL);
|
||||||
assert((cursor = TLV::write_to_memory(backend, cursor, rec2)) != NULL);
|
assert((cursor = TLV::WriteToMemory(backend, cursor, rec2)) != NULL);
|
||||||
assert(TLV::write_to_memory(backend, cursor, rec3) != NULL);
|
assert(TLV::WriteToMemory(backend, cursor, rec3) != NULL);
|
||||||
cursor = NULL;
|
cursor = NULL;
|
||||||
|
|
||||||
// the cursor should point at the next record,
|
// the cursor should point at the next record,
|
||||||
// and rec4 should contain the same data as rec1.
|
// and rec4 should contain the same data as rec1.
|
||||||
cursor = TLV::find_tag(backend, cursor, rec4);
|
cursor = TLV::FindTag(backend, cursor, rec4);
|
||||||
assert(cursor != NULL);
|
assert(cursor != NULL);
|
||||||
assert(cursor != backend.store);
|
assert(cursor != backend.Store);
|
||||||
assert(cmp_record(rec1, rec4));
|
assert(cmp_record(rec1, rec4));
|
||||||
|
|
||||||
cursor = TLV::find_tag(backend, cursor, rec4);
|
cursor = TLV::FindTag(backend, cursor, rec4);
|
||||||
assert(cursor != NULL);
|
assert(cursor != NULL);
|
||||||
assert(cmp_record(rec3, rec4));
|
assert(cmp_record(rec3, rec4));
|
||||||
|
|
||||||
TLV::set_record(rec4, 3, TEST_STRLEN3, TEST_STR3);
|
TLV::SetRecord(rec4, 3, TEST_STRLEN3, TEST_STR3);
|
||||||
assert(TLV::write_to_memory(backend, NULL, rec4));
|
assert(TLV::WriteToMemory(backend, NULL, rec4));
|
||||||
|
|
||||||
rec4.Tag = 2;
|
rec4.Tag = 2;
|
||||||
cursor = TLV::find_tag(backend, NULL, rec4);
|
cursor = TLV::FindTag(backend, NULL, rec4);
|
||||||
assert(cursor != NULL);
|
assert(cursor != NULL);
|
||||||
|
|
||||||
TLV::delete_record(backend, cursor);
|
TLV::DeleteRecord(backend, cursor);
|
||||||
assert(cursor[0] == 3);
|
assert(cursor[0] == 3);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -73,6 +54,8 @@ tlv_test_suite(Arena &backend)
|
||||||
bool
|
bool
|
||||||
run_suite(Arena &backend, const char *label)
|
run_suite(Arena &backend, const char *label)
|
||||||
{
|
{
|
||||||
|
DisplayArena(backend);
|
||||||
|
|
||||||
std::cout << "running test suite " << label << ": ";
|
std::cout << "running test suite " << label << ": ";
|
||||||
if (!tlv_test_suite(backend)) {
|
if (!tlv_test_suite(backend)) {
|
||||||
std::cout << "FAILED" << std::endl;
|
std::cout << "FAILED" << std::endl;
|
||||||
|
@ -81,7 +64,7 @@ run_suite(Arena &backend, const char *label)
|
||||||
std::cout << "OK" << std::endl;
|
std::cout << "OK" << std::endl;
|
||||||
|
|
||||||
std::cout << "\tdestroying arena: ";
|
std::cout << "\tdestroying arena: ";
|
||||||
if (arena_destroy(backend) != 0) {
|
if (DestroyArena(backend) != 0) {
|
||||||
std::cout << "FAILED" << std::endl;
|
std::cout << "FAILED" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -98,27 +81,32 @@ main(int argc, const char *argv[])
|
||||||
Arena arena_mem;
|
Arena arena_mem;
|
||||||
Arena arena_file;
|
Arena arena_file;
|
||||||
|
|
||||||
std::cout << "TESTPROG: " << argv[0] << std::endl;
|
std::cout << "TESTPROG: " << argv[0] << std::endl;
|
||||||
|
InitializeArena(arena_static);
|
||||||
|
InitializeArena(arena_mem);
|
||||||
|
InitializeArena(arena_file);
|
||||||
|
|
||||||
if (-1 == new_arena(arena_static, arena_buffer, ARENA_SIZE)) {
|
if (-1 == NewStaticArena(arena_static, arena_buffer, ARENA_SIZE)) {
|
||||||
abort();
|
abort();
|
||||||
} else if (!run_suite(arena_static, "arena_static")) {
|
} else if (!run_suite(arena_static, "arena_static")) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
ClearArena(arena_static);
|
||||||
|
|
||||||
if (-1 == create_arena(arena_file, ARENA_FILE, ARENA_SIZE, 0644)) {
|
#if defined(__linux__)
|
||||||
|
if (-1 == CreateArena(arena_file, ARENA_FILE, ARENA_SIZE, 0644)) {
|
||||||
abort();
|
abort();
|
||||||
} else if (!run_suite(arena_file, "arena_file")) {
|
} else if (!run_suite(arena_file, "arena_file")) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (-1 == alloc_new_arena(arena_mem, ARENA_SIZE)) {
|
if (-1 == AllocNewArena(arena_mem, ARENA_SIZE)) {
|
||||||
abort();
|
abort();
|
||||||
} else if (!run_suite(arena_mem, "arena_mem")) {
|
} else if (!run_suite(arena_mem, "arena_mem")) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::cout << "OK" << std::endl;
|
std::cout << "OK" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue