699 lines
19 KiB
C
699 lines
19 KiB
C
#include "base_core.h"
|
|
#include "arena.h"
|
|
#include "mini_arena.h"
|
|
#include "platform.h"
|
|
#include "pool.h"
|
|
#include "string.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
|
|
void arena_dump(const Arena *arena)
|
|
{
|
|
return;
|
|
MemoryBlock *block = arena->current;
|
|
puts("@@@@@@@@@@");
|
|
while (block) {
|
|
puts("-----Arena-----");
|
|
printf("base: %p\n", block->base);
|
|
printf("size: %u\n", block->size);
|
|
printf("first_free: %u\n", block->first_free);
|
|
printf("total_used: %lu\n",block->arena_offset);
|
|
printf("prev: %p\n", block->prev);
|
|
puts("-----Arena end-");
|
|
block = block->prev;
|
|
}
|
|
}
|
|
static void arena_test_1(void)
|
|
{
|
|
TRACEF("\n");
|
|
ArenaOptions arena_params = {};
|
|
U32 arena_size = MB(1) + MemoryBlock_Header_Size;
|
|
U32 commit_size = KB(8);
|
|
arena_params.size = arena_size;
|
|
arena_params.commit_size = commit_size;
|
|
Arena arena;
|
|
arena_init(&arena, &arena_params);
|
|
arena_dump(&arena);
|
|
void *ptr = arena_push(&arena, 512, 1);
|
|
MemoryZero(ptr, 512);
|
|
printf("Allocated ptr %p\n", ptr);
|
|
arena_dump(&arena);
|
|
ptr = arena_push(&arena, 512, 1);
|
|
MemoryZero(ptr, 512);
|
|
printf("Allocated ptr %p\n", ptr);
|
|
arena_dump(&arena);
|
|
|
|
ptr = arena_push(&arena, 1, 1);
|
|
MemoryZero(ptr, 1);
|
|
printf("Allocated ptr %p\n", ptr);
|
|
arena_dump(&arena);
|
|
arena_free(&arena);
|
|
}
|
|
|
|
static void arena_test_2(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
ArenaOptions arena_params = {};
|
|
U32 arena_size = MB(3) + MemoryBlock_Header_Size;
|
|
U32 commit_size = KB(72);
|
|
U32 push_size = KB(32);
|
|
arena_params.size = arena_size;
|
|
arena_params.commit_size = commit_size;
|
|
Arena arena;
|
|
arena_init(&arena, &arena_params);
|
|
|
|
void *ptr;
|
|
ptr = arena_push(&arena, push_size, 8);
|
|
MemoryZero(ptr, push_size);
|
|
printf("Allocated ptr %p\n", ptr);
|
|
|
|
arena_dump(&arena);
|
|
ATemp checkpoint = arena_temp_begin(&arena);
|
|
ptr = arena_push(&arena, MB(4)+3, 8);
|
|
MemoryZero(ptr, MB(2));
|
|
|
|
ptr = arena_push(&arena, commit_size * 3, 8);
|
|
MemoryZero(ptr, commit_size * 3 );
|
|
ptr = arena_push(&arena, commit_size , 8);
|
|
MemoryZero(ptr, commit_size );
|
|
|
|
ATemp checkpoint2 = arena_temp_begin(&arena);
|
|
ptr = arena_push(&arena, 64, 8);
|
|
MemoryZero(ptr, 64);
|
|
|
|
arena_temp_end(&checkpoint2);
|
|
|
|
arena_temp_end(&checkpoint);
|
|
arena_reset_to(&arena, 1088);
|
|
arena_dump(&arena);
|
|
ptr = arena_push(&arena, 1, KB(16));
|
|
((U8*)ptr)[0] = 0x37;
|
|
ptr = arena_push(&arena, 1, KB(16));
|
|
((U8*)ptr)[0] = 0x73;
|
|
ptr = arena_push(&arena, 0, KB(4));
|
|
//((U8*)ptr)[0] = 0x73;
|
|
// arena_reset_to(&arena, 1089);
|
|
arena_dump(&arena);
|
|
arena_reset_to(&arena, 0);
|
|
for (U64 i = 0; i < MB(4); i++) {
|
|
ptr = arena_push(&arena, 3, 1);
|
|
MemoryZero(ptr, 3);
|
|
}
|
|
arena_free(&arena);
|
|
}
|
|
|
|
static void arena_test_3(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
ArenaOptions arena_params = {};
|
|
U32 arena_size = KB(97) + MemoryBlock_Header_Size;
|
|
U32 commit_size = KB(97);
|
|
arena_params.size = arena_size;
|
|
arena_params.commit_size = commit_size;
|
|
Arena arena;
|
|
arena_init(&arena, &arena_params);
|
|
arena_dump(&arena);
|
|
void *ptr = arena_push(&arena, KB(64), 32);
|
|
MemoryZero(ptr, KB(64));
|
|
printf("Allocated ptr %p\n", ptr);
|
|
arena_dump(&arena);
|
|
ptr = arena_push(&arena, KB(97) - KB(64), 32);
|
|
MemoryZero(ptr, KB(97) - KB(64));
|
|
printf("Allocated ptr %p\n", ptr);
|
|
arena_dump(&arena);
|
|
arena_free(&arena);
|
|
}
|
|
|
|
// Exercises the alignment-padding edge case: a fresh block has first_free at
|
|
// MemoryBlock_Header_Size (64), so a large alignment pushes the user pointer
|
|
// well past the header. Requesting (block_size - 64) bytes with page alignment
|
|
// previously tripped the end_pos <= block->size assert because the alignment
|
|
// gap was not accounted for. After the fix this should allocate a larger block.
|
|
static void arena_test_4(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
U32 page_size = platform_page_size();
|
|
ArenaOptions arena_params = {};
|
|
U32 arena_size = MB(1) + MemoryBlock_Header_Size;
|
|
U32 commit_size = KB(64);
|
|
arena_params.size = arena_size;
|
|
arena_params.commit_size = commit_size;
|
|
Arena arena;
|
|
arena_init(&arena, &arena_params);
|
|
|
|
// block_size is the page-aligned arena_size. Request nearly the whole block
|
|
// but with page alignment, so the alignment gap (a full page) forces a grow.
|
|
U32 block_size = arena.block_size;
|
|
U32 push_size = block_size - MemoryBlock_Header_Size;
|
|
|
|
void *ptr = arena_push(&arena, push_size, page_size);
|
|
Assert(IsAlignedTo((uintptr_t)ptr, page_size));
|
|
MemoryZero(ptr, push_size);
|
|
printf("test_4: allocated %u bytes page-aligned at %p\n", push_size, ptr);
|
|
arena_dump(&arena);
|
|
|
|
// A second page-aligned push to make sure the cursor math still holds.
|
|
ptr = arena_push(&arena, page_size, page_size);
|
|
Assert(IsAlignedTo((uintptr_t)ptr, page_size));
|
|
MemoryZero(ptr, page_size);
|
|
printf("test_4: allocated %u bytes page-aligned at %p\n", page_size, ptr);
|
|
|
|
arena_free(&arena);
|
|
}
|
|
|
|
static void arena_test_allocator_interface(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
U32 page_size = platform_page_size();
|
|
ArenaOptions arena_params = {};
|
|
U32 arena_size = MB(1) + MemoryBlock_Header_Size;
|
|
U32 commit_size = KB(64);
|
|
arena_params.size = arena_size;
|
|
arena_params.commit_size = commit_size;
|
|
Arena arena;
|
|
arena_init(&arena, &arena_params);
|
|
Allocator allocator = arena_allocator(&arena);
|
|
|
|
// block_size is the page-aligned arena_size. Request nearly the whole block
|
|
// but with page alignment, so the alignment gap (a full page) forces a grow.
|
|
U32 block_size = arena.block_size;
|
|
U32 push_size = block_size - MemoryBlock_Header_Size;
|
|
|
|
void *ptr = allocator_push(&allocator, push_size, page_size);
|
|
Assert(IsAlignedTo((uintptr_t)ptr, page_size));
|
|
MemoryZero(ptr, push_size);
|
|
printf("test_4: allocated %u bytes page-aligned at %p\n", push_size, ptr);
|
|
arena_dump(&arena);
|
|
|
|
// A second page-aligned push to make sure the cursor math still holds.
|
|
ptr = allocator_push(&allocator, page_size, page_size);
|
|
Assert(IsAlignedTo((uintptr_t)ptr, page_size));
|
|
MemoryZero(ptr, page_size);
|
|
printf("test_4: allocated %u bytes page-aligned at %p\n", page_size, ptr);
|
|
|
|
allocator_free_all(&allocator);
|
|
arena_free(&arena);
|
|
|
|
}
|
|
|
|
static void arena_test_decommit(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
U32 page_size = platform_page_size();
|
|
ArenaOptions arena_params = {};
|
|
U32 arena_size = MB(1) + MemoryBlock_Header_Size;
|
|
U32 commit_size = KB(64);
|
|
arena_params.size = arena_size;
|
|
arena_params.commit_size = commit_size;
|
|
Arena arena;
|
|
arena_init(&arena, &arena_params);
|
|
void *ptr = arena_push(&arena, commit_size * 10, 8);
|
|
MemoryZero(ptr, commit_size * 10);
|
|
arena_reset(&arena);
|
|
|
|
void *pre_ptr = arena_push(&arena, 5, 4);
|
|
|
|
ATemp tmp = arena_temp_begin(&arena);
|
|
ptr = arena_push(&arena, commit_size * 2 + 13, 8);
|
|
MemoryZero(ptr, commit_size * 2 + 13);
|
|
arena_temp_end(&tmp);
|
|
MemoryZero(pre_ptr, 5);
|
|
|
|
arena_free(&arena);
|
|
}
|
|
|
|
void miniarena_test1(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
#define arena_size 4096
|
|
MARENA_DEFINE(arena, arena_size, 8);
|
|
int i;
|
|
for (i = 0; ; i++) {
|
|
void *ptr = marena_push(&arena, 1);
|
|
if (ptr == NULL) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
printf("miniarena_test1,size %u pushed %d bytes first_free %u\n", arena.size, i, arena.first_free);
|
|
marena_reset(&arena);
|
|
MTemp checkpoint = marena_temp_begin(&arena);
|
|
|
|
void *ptr = marena_push(&arena, arena_size);
|
|
Assert(ptr != NULL);
|
|
Assert(arena.first_free == arena_size);
|
|
MemoryZero(ptr, arena_size);
|
|
marena_temp_end(&checkpoint);
|
|
Assert(arena.first_free == 0);
|
|
U32 *val = marena_push_type(&arena, U32);
|
|
*val = 0xa0b0c0d0;
|
|
printf("marena val 0x%x\n", *val);
|
|
|
|
printf("miniarena_test1,size %u bytes first_free %u\n", arena.size, arena.first_free);
|
|
Assert(arena.first_free == sizeof(U32));
|
|
}
|
|
|
|
typedef struct PoolTest PoolTest;
|
|
struct PoolTest{
|
|
U32 n;
|
|
PoolTest *next;
|
|
char name[12];
|
|
};
|
|
|
|
void apool_test(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
Arena arena;
|
|
arena_init(&arena, &ArenaOptions_Default);
|
|
Allocator allocator = arena_allocator(&arena);
|
|
APool *pool = apool_create_ex(&allocator, 16, sizeof(PoolTest), alignof(PoolTest));
|
|
PoolTest *list = NULL;
|
|
for (U32 i = 0; i < U32_Max; i++) {
|
|
PoolTest *pt = apool_alloc(pool);
|
|
if (pt == NULL){
|
|
break;
|
|
}
|
|
pt->n = i;
|
|
pt->next = list;
|
|
list = pt;
|
|
}
|
|
for (PoolTest *p = list; p; p = p->next){
|
|
printf("Pooltest %u\n",p->n);
|
|
}
|
|
|
|
PoolTest *next;
|
|
U32 count = 0;
|
|
for (PoolTest *p = list; count < 7 && p; p = next){
|
|
count++;
|
|
next = p->next;
|
|
printf("Pooltest freeing %u\n",p->n);
|
|
apool_free(pool, p);
|
|
}
|
|
list = NULL;
|
|
for (U32 i = 0; i < U32_Max; i++) {
|
|
PoolTest *pt = apool_alloc(pool);
|
|
if (pt == NULL){
|
|
break;
|
|
}
|
|
pt->n = i;
|
|
pt->next = list;
|
|
list = pt;
|
|
}
|
|
for (PoolTest *p = list; p; p = p->next){
|
|
printf("Pooltest %u\n",p->n);
|
|
}
|
|
allocator_free_all(&allocator);
|
|
arena_free(&arena);
|
|
}
|
|
|
|
void apool_test_miniarena(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
MArena arena;
|
|
U8 data[4096];
|
|
marena_init(&arena, data, sizeof data);
|
|
Allocator allocator = marena_allocator(&arena);
|
|
APool *pool = apool_create_ex(&allocator, 16, sizeof(PoolTest), alignof(PoolTest));
|
|
PoolTest *list = NULL;
|
|
for (U32 i = 0; i < U32_Max; i++) {
|
|
PoolTest *pt = apool_alloc(pool);
|
|
if (pt == NULL){
|
|
break;
|
|
}
|
|
pt->n = i;
|
|
pt->next = list;
|
|
list = pt;
|
|
}
|
|
for (PoolTest *p = list; p; p = p->next){
|
|
printf("Pooltest %u\n",p->n);
|
|
}
|
|
|
|
PoolTest *next;
|
|
U32 count = 0;
|
|
for (PoolTest *p = list; count < 7 && p; p = next){
|
|
count++;
|
|
next = p->next;
|
|
printf("Pooltest freeing %u\n",p->n);
|
|
apool_free(pool, p);
|
|
}
|
|
list = NULL;
|
|
for (U32 i = 0; i < U32_Max; i++) {
|
|
PoolTest *pt = apool_alloc(pool);
|
|
if (pt == NULL){
|
|
break;
|
|
}
|
|
pt->n = i;
|
|
pt->next = list;
|
|
list = pt;
|
|
}
|
|
for (PoolTest *p = list; p; p = p->next){
|
|
printf("Pooltest %u\n",p->n);
|
|
}
|
|
allocator_free_all(&allocator);
|
|
}
|
|
|
|
|
|
void apool_test_autogrow(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
Arena arena;
|
|
arena_init(&arena, &ArenaOptions_Default);
|
|
Allocator allocator = arena_allocator(&arena);
|
|
|
|
APool *pool = apool_create(&allocator, APOOL_AUTOGROW, PoolTest);
|
|
PoolTest *list = NULL;
|
|
for (U32 i = 0; i < 4; i++) {
|
|
PoolTest *pt = apool_alloc(pool);
|
|
if (pt == NULL){
|
|
break;
|
|
}
|
|
pt->n = i;
|
|
pt->next = list;
|
|
list = pt;
|
|
}
|
|
for (PoolTest *p = list; p; p = p->next){
|
|
printf("Pooltest %u\n",p->n);
|
|
}
|
|
|
|
PoolTest *next;
|
|
U32 count = 0;
|
|
for (PoolTest *p = list; count < 3 && p; p = next){
|
|
count++;
|
|
next = p->next;
|
|
printf("Pooltest freeing %u\n",p->n);
|
|
apool_free(pool, p);
|
|
}
|
|
list = NULL;
|
|
for (U32 i = 0; i < 5; i++) {
|
|
PoolTest *pt = apool_alloc(pool);
|
|
if (pt == NULL){
|
|
break;
|
|
}
|
|
pt->n = i;
|
|
pt->next = list;
|
|
list = pt;
|
|
}
|
|
for (PoolTest *p = list; p; p = p->next){
|
|
printf("Pooltest %u\n",p->n);
|
|
}
|
|
|
|
allocator_free_all(&allocator);
|
|
arena_free(&arena);
|
|
|
|
}
|
|
|
|
void string_test_1(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
Str str1 = S("Hello");
|
|
printf("str1: %.*s len %d\n", str1.len, str1.str, str1.len);
|
|
U64 str1_index_of_l = str_find_byte(str1, 'l');
|
|
U64 str1_index_of_g = str_find_byte(str1, 'g');
|
|
printf("str1: index of l %ld, index of g: %ld\n", str1_index_of_l, str1_index_of_g);
|
|
|
|
MARENA_DEFINE(arena, 512, 1);
|
|
Allocator alloc = marena_allocator(&arena);
|
|
Str str2 = str_dup(&alloc, S(" World"));
|
|
Str str3 = str_concat(&alloc, str1, str2);
|
|
printf("str3: %.*s len %d\n", str3.len, str3.str, str3.len);
|
|
}
|
|
|
|
void string_split_test_1(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
Str str1 = S("|a:bb|ccc|");
|
|
Str sep = S("|:");
|
|
STRVEC_DEFINE(strings, 16);
|
|
|
|
str_split(str1, sep, &strings);
|
|
for (U32 i = 0; i < strings.len; i++) {
|
|
Str *str = &strings.strings[i];
|
|
printf("split %u: '%.*s'\n", i, str->len, str->str);
|
|
}
|
|
}
|
|
void string_test_misc(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
Str str1 = S("Hello World");
|
|
bool prefix1 = str_starts_with(str1, S("He"));
|
|
bool prefix2 = str_starts_with(str1, S(""));
|
|
bool prefix3 = str_starts_with(str1, S("false"));
|
|
bool prefix4 = str_starts_with(str1, S("Hello World"));
|
|
|
|
bool suffix1 = str_ends_with(str1, S("orld"));
|
|
bool suffix2 = str_ends_with(str1, S(""));
|
|
bool suffix3 = str_ends_with(str1, S("false"));
|
|
bool suffix4 = str_ends_with(str1, S("Hello World"));
|
|
printf("matches: %d %d %d %d %d %d %d %d\n", prefix1, prefix2, prefix3, prefix4, suffix1, suffix2, suffix3, suffix4);
|
|
|
|
Str str2 = S(" Hello World\t \n");
|
|
Str str2_trim = str_ascii_trim(str2);
|
|
printf("str2_trim: '%.*s'\n", str2_trim.len, str2_trim.str);
|
|
printf("str2_trim == str1: %d\n", str_eq(str1, str2_trim));
|
|
|
|
Str str3 = str_empty();
|
|
Str str3_trim = str_ascii_trim(str3);
|
|
printf("str3_trim: '%.*s'\n", str3_trim.len, str3_trim.str);
|
|
|
|
Str str4 = S(" \t\t ");
|
|
Str str4_trim = str_ascii_trim(str4);
|
|
printf("str4_trim: '%.*s'\n", str4_trim.len, str4_trim.str);
|
|
|
|
S64 found = str_index(str1, S("World"));
|
|
printf("1. found %ld\n", found);
|
|
found = str_index(str_empty(), S("World"));
|
|
printf("2. found %ld\n", found);
|
|
found = str_index(str_empty(), S(""));
|
|
printf("3. found %ld\n", found);
|
|
found = str_index(str1, S(" "));
|
|
printf("4. found %ld\n", found);
|
|
|
|
}
|
|
void string_test_join(void)
|
|
{
|
|
TRACEF("\n");
|
|
Arena arena;
|
|
arena_init(&arena, &ArenaOptions_Default);
|
|
Allocator allocator = arena_allocator(&arena);
|
|
Str strs[3] = {S("1"), S("two"), S("3-3")};
|
|
StrVec vec = STRVEC_STATIC_INITIALIZER(strs);
|
|
|
|
Str str = str_join(&allocator, vec, S("/"));
|
|
printf("str_join 1 '%.*s'\n", str.len, str.str);
|
|
str = str_join(&allocator, vec, S(""));
|
|
printf("str_join 2 '%.*s'\n", str.len, str.str);
|
|
vec.len = 0;
|
|
str = str_join(&allocator, vec, S("/"));
|
|
printf("str_join 2 '%.*s'\n", str.len, str.str);
|
|
|
|
}
|
|
|
|
void print_runes(Str str)
|
|
{
|
|
U32 offset = 0;
|
|
U32 len = str_rune_count(str);
|
|
printf("rune len %d\n", len);
|
|
while (offset < str.len) {
|
|
RuneDecode d = str_utf8_decode(str, offset);
|
|
printf("Rune: %d valid: %d\n", d.rune, d.valid);
|
|
offset += d.width;
|
|
}
|
|
}
|
|
|
|
void string_test_utf8(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
Str str1 = S("Test 1ø2 ☺");
|
|
|
|
TRACEF("str1:\n");
|
|
print_runes(str1);
|
|
|
|
Str str2 = str_empty();
|
|
TRACEF("str2:\n");
|
|
print_runes(str2);
|
|
|
|
Str str3 = S("1Å 2\xc6" "3\xc3");
|
|
TRACEF("str3:\n");
|
|
print_runes(str3);
|
|
|
|
const char rune_error[] = {0xEF, 0xBF, 0xBD, 0x00} ; // RUNE_ERROR encoded in utf-8
|
|
Str str4 = S(rune_error);
|
|
TRACEF("str4:\n");
|
|
print_runes(str4); // this should be a valid code point
|
|
|
|
}
|
|
|
|
void string_test_hex(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
MArena arena;
|
|
U8 data[4096];
|
|
marena_init(&arena, data, sizeof data);
|
|
Allocator allocator = marena_allocator(&arena);
|
|
|
|
Str str1 = S("Hello World ☺");
|
|
|
|
Str str1_encoded = str_hex_encode_alloc(&allocator, str1);
|
|
printf("str1_encoded: '%.*s'\n", str1_encoded.len, str1_encoded.str);
|
|
|
|
Str str1_decoded = str_hex_decode_alloc(&allocator, str1_encoded);
|
|
printf("str1_decoded: '%.*s'\n", str1_decoded.len, str1_decoded.str);
|
|
|
|
Str str2 = S("");
|
|
|
|
Str str2_encoded = str_hex_encode_alloc(&allocator, str2);
|
|
printf("str2_encoded: '%.*s'\n", str2_encoded.len, str2_encoded.str);
|
|
|
|
Str str2_decoded = str_hex_decode_alloc(&allocator, str2_encoded);
|
|
printf("str2_decoded: '%.*s'\n", str2_decoded.len, str2_decoded.str);
|
|
}
|
|
|
|
typedef struct StrSLNode StrSLNode;
|
|
struct StrSLNode {
|
|
Str str;
|
|
StrSLNode *next;
|
|
};
|
|
|
|
typedef struct StrSList StrSList;
|
|
struct StrSList {
|
|
StrSLNode *first;
|
|
StrSLNode **last;
|
|
};
|
|
|
|
void string_test_slist(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
Str str1 = S("one");
|
|
Str str2 = S("two");
|
|
Str str3 = S("three");
|
|
StrSList strlist = {};
|
|
StrSLNode n1 = {str1, NULL};
|
|
StrSLNode n2 = {str2, NULL};
|
|
StrSLNode n3 = {str3, NULL};
|
|
|
|
SListInit(&strlist);
|
|
SListAddFirst(&strlist, &n1);
|
|
SListAddFirst(&strlist, &n2);
|
|
SListAddFirst(&strlist, &n3);
|
|
TRACEF("List test first\n");
|
|
|
|
for (StrSLNode *n = strlist.first; n != NULL; n = n->next) {
|
|
printf("Node: %.*s\n", n->str.len, n->str.str);
|
|
}
|
|
TRACEF("List test first done\n");
|
|
SListInit(&strlist);
|
|
SListAddLast(&strlist, &n1);
|
|
SListAddLast(&strlist, &n2);
|
|
SListAddLast(&strlist, &n3);
|
|
SListRemoveFirst(&strlist);
|
|
TRACEF("List test last\n");
|
|
|
|
for (StrSLNode *n = strlist.first; n != NULL; n = n->next) {
|
|
printf("Node: %.*s\n", n->str.len, n->str.str);
|
|
}
|
|
TRACEF("List test last done\n");
|
|
|
|
}
|
|
typedef struct StrDLNode StrDLNode;
|
|
struct StrDLNode {
|
|
Str str;
|
|
StrDLNode *next;
|
|
StrDLNode *prev;
|
|
};
|
|
|
|
typedef struct StrDList StrDList;
|
|
struct StrDList {
|
|
StrDLNode *first;
|
|
StrDLNode *last;
|
|
};
|
|
|
|
void string_test_dlist(void)
|
|
{
|
|
TRACEF("\n");
|
|
|
|
Str str1 = S("one");
|
|
Str str2 = S("two");
|
|
Str str3 = S("three");
|
|
Str str4 = S("four");
|
|
StrDList strlist = {};
|
|
StrDLNode n1 = {str1, NULL, NULL};
|
|
StrDLNode n2 = {str2, NULL, NULL};
|
|
StrDLNode n3 = {str3, NULL, NULL};
|
|
StrDLNode n4 = {str4, NULL, NULL};
|
|
|
|
DListInit(&strlist);
|
|
DListAddFirst(&strlist, &n1);
|
|
DListAddFirst(&strlist, &n2);
|
|
DListAddFirst(&strlist, &n3);
|
|
TRACEF("List test first\n");
|
|
|
|
for (StrDLNode *n = strlist.first; n != NULL; n = n->next) {
|
|
printf("Node: %.*s\n", n->str.len, n->str.str);
|
|
}
|
|
TRACEF("List test first done\n");
|
|
|
|
DListInit(&strlist);
|
|
DListAddLast(&strlist, &n2);
|
|
DListAddLast(&strlist, &n3);
|
|
DListAddLast(&strlist, &n4);
|
|
DListAddFirst(&strlist, &n1);
|
|
|
|
TRACEF("List test full\n");
|
|
|
|
for (StrDLNode *n = strlist.first; n != NULL; n = n->next) {
|
|
printf("Node: %.*s\n", n->str.len, n->str.str);
|
|
}
|
|
TRACEF("List test full done\n");
|
|
|
|
DListRemove(&strlist, &n1);
|
|
DListRemoveFirst(&strlist);
|
|
DListRemoveLast(&strlist);
|
|
TRACEF("List test tail removed\n");
|
|
|
|
for (StrDLNode *n = strlist.first; n != NULL; n = n->next) {
|
|
printf("Node: %.*s\n", n->str.len, n->str.str);
|
|
}
|
|
TRACEF("List test tail removed done\n");
|
|
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
arena_test_1();
|
|
arena_test_2();
|
|
arena_test_3();
|
|
arena_test_4();
|
|
arena_test_decommit();
|
|
arena_test_allocator_interface();
|
|
miniarena_test1();
|
|
apool_test();
|
|
apool_test_autogrow();
|
|
apool_test_miniarena();
|
|
string_test_1();
|
|
string_split_test_1();
|
|
string_test_misc();
|
|
string_test_join();
|
|
string_test_utf8();
|
|
string_test_hex();
|
|
string_test_slist();
|
|
string_test_dlist();
|
|
|
|
}
|
|
|