+#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "array.h"
+Array array_create(size_t membsiz)
+{
+ return (Array) {
+ .membsiz = membsiz,
+ .siz = 0,
+ .cap = 0,
+ .ptr = NULL,
+ .cmp = NULL,
+ };
+}
+
+
static void array_realloc(Array *array)
{
if (array->siz > array->cap) {
memcpy((char *) array->ptr + oldsiz * array->membsiz, elem, array->membsiz);
}
-Array array_create(size_t membsiz)
+ArraySearchResult array_search(Array *array, void *search)
{
- return (Array) {
- .membsiz = membsiz,
- .siz = 0,
- .cap = 0,
- .ptr = NULL,
- };
+ assert(array->cmp);
+ size_t min, max, index;
+
+ min = index = 0;
+ max = array->siz;
+
+ while (min < max) {
+ index = min;
+
+ size_t mid = (max + min) / 2;
+ s8 state = array->cmp(search, (char *) array->ptr + mid * array->membsiz);
+
+ if (state == 0)
+ return (ArraySearchResult) {true, mid};
+ else if (state > 0)
+ max = mid;
+ else
+ min = mid;
+ }
+
+ return (ArraySearchResult) {false, index};
}
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
-#include "binsearch.h"
#include "map.h"
#include "util.h"
-Map *map_create()
+#define CMPBOUNDS(x) x == 0 ? 0 : x > 0 ? 1 : -1
+
+static s8 sector_compare(void *hash, void *sector)
{
- Map *map = malloc(sizeof(Map));
- map->sectors = array_create(sizeof(MapSector *));
- return map;
+ s64 d = *((u64 *) hash) - ((MapSector *) sector)->hash;
+ return CMPBOUNDS(d);
+}
+
+static s8 block_compare(void *level, void *block)
+{
+ s32 d = *((s32 *) level) - ((MapBlock *) block)->pos.y;
+ return CMPBOUNDS(d);
+}
+
+static MapBlock *allocate_block(v3s32 pos)
+{
+ MapBlock *block = malloc(sizeof(MapBlock));
+ block->pos = pos;
+ block->extra = NULL;
+ return block;
}
static MapBlock **get_block_ptr(MapSector *sector, size_t idx)
return (MapSector **) map->sectors.ptr + idx;
}
+Map *map_create()
+{
+ Map *map = malloc(sizeof(Map));
+ map->sectors = array_create(sizeof(MapSector *));
+ map->sectors.cmp = §or_compare;
+ return map;
+}
+
void map_delete(Map *map)
{
for (size_t s = 0; s < map->sectors.siz; s++) {
free(map);
}
-#define CMPBOUNDS(x) x == 0 ? 0 : x > 0 ? 1 : -1
-
-static s8 sector_compare(void *hash, void *sector)
-{
- s64 d = *((u64 *) hash) - ((MapSector *) sector)->hash;
- return CMPBOUNDS(d);
-}
-
MapSector *map_get_sector(Map *map, v2s32 pos, bool create)
{
u64 hash = ((u64) pos.x << 32) + (u64) pos.y;
- BinsearchResult res = binsearch(&hash, map->sectors.ptr, map->sectors.siz, §or_compare);
+ ArraySearchResult res = array_search(&map->sectors, &hash);
if (res.success)
return *get_sector_ptr(map, res.index);
sector->pos = pos;
sector->hash = hash;
sector->blocks = array_create(sizeof(MapBlock *));
+ sector->blocks.cmp = &block_compare;
array_insert(&map->sectors, §or, res.index);
return sector;
}
-static s8 block_compare(void *level, void *block)
-{
- s32 d = *((s32 *) level) - ((MapBlock *) block)->pos.y;
- return CMPBOUNDS(d);
-}
-
-static MapBlock *allocate_block(v3s32 pos)
-{
- MapBlock *block = malloc(sizeof(MapBlock));
- block->pos = pos;
- block->extra = NULL;
- return block;
-}
-
MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
{
MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, create);
if (! sector)
return NULL;
- BinsearchResult res = binsearch(&pos.y, sector->blocks.ptr, sector->blocks.siz, &block_compare);
+ ArraySearchResult res = array_search(§or->blocks, &pos.y);
MapBlock *block = NULL;
void map_add_block(Map *map, MapBlock *block)
{
MapSector *sector = map_get_sector(map, (v2s32) {block->pos.x, block->pos.z}, true);
- BinsearchResult res = binsearch(&block->pos.y, sector->blocks.ptr, sector->blocks.siz, &block_compare);
+ ArraySearchResult res = array_search(§or->blocks, &block->pos.y);
if (res.success) {
MapBlock **ptr = get_block_ptr(sector, res.index);
map_free_block(*ptr);