Thu, 12 Feb 2026 11:20:43 +0100
add pblock_iterator
--- a/src/server/safs/proxy.c Fri Feb 06 19:37:41 2026 +0100 +++ b/src/server/safs/proxy.c Thu Feb 12 11:20:43 2026 +0100 @@ -30,11 +30,14 @@ #include "../util/pblock.h" +#include "../proxy/httpclient.h" + int http_reverse_proxy_service(pblock *param, Session *sn, Request *rq) { + EventHandler *ev = sn->ev; + + HttpClient *client = http_client_new(ev); - EventHandler *ev = sn->ev; - - return REQ_ABORTED; + return REQ_PROCESSING; }
--- a/src/server/test/main.c Fri Feb 06 19:37:41 2026 +0100 +++ b/src/server/test/main.c Thu Feb 12 11:20:43 2026 +0100 @@ -43,6 +43,7 @@ #include "test.h" #include "httpparser.h" +#include "pblock.h" #include "vfs.h" #include "writer.h" #include "xml.h" @@ -82,6 +83,7 @@ cx_test_register(suite, test_util_uri_escape_space); cx_test_register(suite, test_util_uri_escape_latin); cx_test_register(suite, test_util_uri_escape_kanji); + cx_test_register(suite, test_pblock_iterator); // httpparser tests cx_test_register(suite, test_parse_request_line);
--- a/src/server/test/objs.mk Fri Feb 06 19:37:41 2026 +0100 +++ b/src/server/test/objs.mk Thu Feb 12 11:20:43 2026 +0100 @@ -32,6 +32,7 @@ TESTOBJ = test.o TESTOBJ += main.o +TESTOBJ += pblock.o TESTOBJ += httpparser.o TESTOBJ += testutils.o TESTOBJ += webdav.o
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/test/pblock.c Thu Feb 12 11:20:43 2026 +0100 @@ -0,0 +1,144 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pblock.h" + +#include "../util/pblock.h" + +#include <cx/hash_map.h> + +CX_TEST(test_pblock_iterator) { + pool_handle_t *pool = pool_create(); + + CX_TEST_DO { + pblock *pb_empty_1 = pblock_create_pool(pool, 1); + pblock *pb_empty_2 = pblock_create_pool(pool, 2); + pblock *pb_empty_4 = pblock_create_pool(pool, 4); + + pblock *pb_one_1 = pblock_create_pool(pool, 1); + pblock *pb_one_2 = pblock_create_pool(pool, 2); + pblock *pb_one_4 = pblock_create_pool(pool, 4); + + pblock *pb_many_1 = pblock_create_pool(pool, 1); + pblock *pb_many_4 = pblock_create_pool(pool, 4); + pblock *pb_many_16 = pblock_create_pool(pool, 16); + pblock *pb_many_64 = pblock_create_pool(pool, 64); + + pblock_nvinsert("mykey", "pb_one", pb_one_1); + pblock_nvinsert("mykey", "pb_one", pb_one_2); + pblock_nvinsert("mykey", "pb_one", pb_one_4); + + pblock *pbs[4] = { pb_many_1, pb_many_4, pb_many_16, pb_many_64 }; + + for(int n=0;n<4;n++) { + pblock *p = pbs[n]; + pblock_nvinsert("key1", "many1", p); + pblock_nvinsert("key2", "many2", p); + pblock_nvinsert("key3", "many3", p); + pblock_nvinsert("key4", "many4", p); + pblock_nvinsert("b_key5__long_key_X1", "many5", p); + pblock_nvinsert("c_key6__long_key_X2", "many6", p); + pblock_nvinsert("d_key7__long_key_X3", "many7", p); + pblock_nvinsert("e_key8__long_key_X4", "many8", p); + pblock_nvinsert("01_key9__very_long_key_test_X1", "many9", p); + pblock_nvinsert("12_keya__very_long_key_test_X20", "manya", p); + pblock_nvinsert("34_keyb__very_long_key_test_X300", "manyb", p); + pblock_nvinsert("56_keyc__very_long_key_test_X4000", "manyc", p); + pblock_nvinsert("78_keyd__very_long_key_test_X50000", "manyd", p); + } + + int count; + CxIterator i; + + // check empty pblocks + count = 0; + i = pblock_iterator(pb_empty_1); + cx_foreach(pb_entry*, entry, i) { + count++; + } + CX_TEST_ASSERT(count == 0); + + count = 0; + i = pblock_iterator(pb_empty_2); + cx_foreach(pb_entry*, entry, i) { + count++; + } + CX_TEST_ASSERT(count == 0); + + count = 0; + i = pblock_iterator(pb_empty_4); + cx_foreach(pb_entry*, entry, i) { + count++; + } + CX_TEST_ASSERT(count == 0); + + // check pblocks with one element + pblock *pbs_one[3] = { pb_one_1, pb_one_2, pb_one_4 }; + for(int n=0;n<3;n++) { + count = 0; + i = pblock_iterator(pbs_one[n]); + cx_foreach(pb_entry*, entry, i) { + count++; + CX_TEST_ASSERT(entry); + CX_TEST_ASSERT(entry->param); + CX_TEST_ASSERT(entry->param->name); + CX_TEST_ASSERT(entry->param->value); + CX_TEST_ASSERT(!strcmp(entry->param->name, "mykey")); + CX_TEST_ASSERT(!strcmp(entry->param->value, "pb_one")); + } + CX_TEST_ASSERT(count == 1); + } + + // check pblocks with many elements + for(int n=0;n<4;n++) { + CxMap *map = cxHashMapCreate(NULL, CX_STORE_POINTERS, 64); + + i = pblock_iterator(pbs[n]); + cx_foreach(pb_entry*, entry, i) { + CX_TEST_ASSERT(entry); + CX_TEST_ASSERT(entry->param); + CX_TEST_ASSERT(entry->param->name); + CX_TEST_ASSERT(entry->param->value); + cxMapPut(map, entry->param->name, entry->param->value); + } + CX_TEST_ASSERT(cxMapSize(map) == 13); + + CxMapIterator mi = cxMapIterator(map); + cx_foreach(CxMapEntry*, entry, mi) { + cxmutstr key = cx_strdup(cx_strn(entry->key->data, entry->key->len)); + char *pb_val = pblock_findval(key.ptr, pbs[n]); + free(key.ptr); + char *map_value = entry->value; + CX_TEST_ASSERT(!cx_strcmp(pb_val, map_value)); + } + cxMapFree(map); + } + } + + pool_destroy(pool); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/test/pblock.h Thu Feb 12 11:20:43 2026 +0100 @@ -0,0 +1,46 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEST_PBLOCK_H +#define TEST_PBLOCK_H + +#include "test.h" + +#ifdef __cplusplus +extern "C" { +#endif + +CX_TEST(test_pblock_iterator); + + +#ifdef __cplusplus +} +#endif + +#endif /* TEST_PBLOCK_H */ +
--- a/src/server/util/pblock.c Fri Feb 06 19:37:41 2026 +0100 +++ b/src/server/util/pblock.c Thu Feb 12 11:20:43 2026 +0100 @@ -1423,3 +1423,50 @@ pblock_kvinsert(key, value, valuelen, pb); } } + + +/* ------------------------ UCX Iterator for pblock ------------------------ */ + +static bool pblock_iterator_valid(const void *it) { + const CxIterator *i = it; + return i->elem_handle != NULL; +} + + +static void* pblock_iterator_current(const void *it) { + const CxIterator *i = it; + return i->elem_handle; +} + +static void pblock_iterator_next(void *it) { + CxIterator *i = it; + pblock *p = i->src_handle; + while(i->index < p->hsize) { + pb_entry *entry = i->elem_handle; + if(entry) { + entry = entry->next; + } else { + entry = p->ht[i->index]; + } + + if(entry) { + i->elem_handle = entry; + return; + } + i->elem_handle = NULL; + i->index++; + } +} + + +NSAPI_PUBLIC CxIterator pblock_iterator(pblock *pb) { + CxIterator i; + memset(&i, 0, sizeof(CxIterator)); + i.base.valid = pblock_iterator_valid; + i.base.current = pblock_iterator_current; + i.base.next = pblock_iterator_next; + i.src_handle = pb; + pblock_iterator_next(&i); + return i; +} +
--- a/src/server/util/pblock.h Fri Feb 06 19:37:41 2026 +0100 +++ b/src/server/util/pblock.h Thu Feb 12 11:20:43 2026 +0100 @@ -67,6 +67,8 @@ #define BASE_DLL #endif +#include <cx/iterator.h> + #ifdef INTNSAPI /* --- Begin function prototypes --- */ @@ -348,6 +350,8 @@ #define PARAM_KEY(pp) *(const pb_key **)((pp) + 1) /* new */ +NSAPI_PUBLIC CxIterator pblock_iterator(pblock *pb); + #ifdef __cplusplus } #endif