diff --git a/main.cpp b/main.cpp index 89a4098..ae68fe1 100644 --- a/main.cpp +++ b/main.cpp @@ -105,6 +105,22 @@ void test_basics(amap mapdo, void *map) { assert(NULL != (iptr = (int *)mapdo(map, AMAP_GET, "meaningless1", NULL))); assert(*iptr == 42); assert(iptr == &i); + + /* Check the case where we have same 8-long prefix for multiple and they should be different */ + int long_1 = 1; + int long_2 = 2; + int long_3 = 3; + + assert(NULL != mapdo(map, AMAP_SET, "very_long_test_key_1", &long_1)); + assert(NULL != mapdo(map, AMAP_SET, "very_long_test_key_2", &long_2)); + assert(NULL != mapdo(map, AMAP_SET, "very_long_test_key_3", &long_3)); + + assert(NULL != (iptr = (int *)mapdo(map, AMAP_GET, "very_long_test_key_1", NULL))); + assert(*iptr == 1); + assert(NULL != (iptr = (int *)mapdo(map, AMAP_GET, "very_long_test_key_2", NULL))); + assert(*iptr == 2); + assert(NULL != (iptr = (int *)mapdo(map, AMAP_GET, "very_long_test_key_3", NULL))); + assert(*iptr == 3); } int main() { diff --git a/simap.h b/simap.h index 53f5797..29e831d 100644 --- a/simap.h +++ b/simap.h @@ -128,46 +128,44 @@ static inline simap_ptr64 *simap_search_internal(simap_instance *map, const char /* Lookup prefix (fast-key) - hopefully this gets vectorized (should be)!!! */ auint64 *base = (auint64 *) (map->base); auint64 *end = (auint64 *)((uint8_t *)base + (map->usage_end)); - auint64 *tipp = NULL; - auint64 *nutipp = make_tipp(base, prefix.u64, end); - while(tipp != nutipp) { - tipp = nutipp; - while(tipp < end) { - /* Fast lookup, because found prefix */ - assert((*tipp == prefix.u64)); + auint64 *tipp = make_tipp(base, prefix.u64, end); + while(tipp < end) { - /* First check the remains of the string (only if needed) */ - if(!is_smallkey) { - char *tippremains = (char *)((uint8_t *)tipp + sizeof(uint64_t)); - if(strcmp(keyremains, tippremains) != 0) { - continue; - } - } + /* Need detailed lookup, because found the prefix */ + assert((*tipp == prefix.u64)); - simap_ptr64 *ptr = (simap_ptr64 *)((uint8_t *) (tipp - 2)); - - /* Check back & forth (jump validation) */ - uint32_t previ = *((uint32_t *)(tipp - 1)); - if(previ == (uint32_t) -1) { - /* Expect it be good if it was first insert ever? Statistically rare to be not like it */ - return ptr; - } - uint32_t prevnexi = *(uint32_t *)(((uint8_t *)base) + previ - + sizeof(simap_ptr64) - + sizeof(uint32_t)); - - auint64 *retipp = (auint64 *)(((uint8_t *)base + prevnexi) - + sizeof(simap_ptr64) + sizeof(uint32_t) + - + sizeof(uint32_t)); - - if(retipp != tipp) { + /* First check the remains of the string (only if needed) */ + if(!is_smallkey) { + char *tippremains = (char *)((uint8_t *)tipp + sizeof(uint64_t)); + if(strcmp(keyremains, tippremains) != 0) { + tipp = make_tipp(tipp + 1, prefix.u64, end); continue; } + } - /* Can have the (statistically checked) pointer */ + simap_ptr64 *ptr = (simap_ptr64 *)((uint8_t *) (tipp - 2)); + + /* Check back & forth (jump validation) */ + uint32_t previ = *((uint32_t *)(tipp - 1)); + if(previ == (uint32_t) -1) { + /* Expect it be good if it was first insert ever? Statistically rare to be not like it */ return ptr; } - nutipp = make_tipp((auint64 *) base, prefix.u64, end); + uint32_t prevnexi = *(uint32_t *)(((uint8_t *)base) + previ + + sizeof(simap_ptr64) + + sizeof(uint32_t)); + + auint64 *retipp = (auint64 *)(((uint8_t *)base + prevnexi) + + sizeof(simap_ptr64) + sizeof(uint32_t) + + + sizeof(uint32_t)); + + if(retipp != tipp) { + tipp = make_tipp(tipp + 1, prefix.u64, end); + continue; + } + + /* Can have the (statistically checked) pointer */ + return ptr; } /* Haven't found anything */