mv map util;

This commit is contained in:
bjorn 2022-03-30 12:31:39 -07:00
parent faa42ee38b
commit 5d271de91a
12 changed files with 114 additions and 126 deletions

View File

@ -294,7 +294,6 @@ endforeach()
set(LOVR_SRC
src/core/fs.c
src/core/map.c
src/core/zip.c
src/api/api.c
src/api/l_lovr.c

View File

@ -351,7 +351,6 @@ src = {
'src/util.c',
'src/core/os_' .. target .. '.c',
'src/core/fs.c',
'src/core/map.c',
'src/core/zip.c',
'src/api/api.c',
'src/api/l_lovr.c'

View File

@ -1,7 +1,6 @@
#include "api.h"
#include "data/modelData.h"
#include "core/maf.h"
#include "core/map.h"
#include "shaders.h"
#include <lua.h>
#include <lauxlib.h>

View File

@ -1,100 +0,0 @@
#include "map.h"
#include "util.h"
#include <stdlib.h>
#include <string.h>
static uint32_t prevpo2(uint32_t x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x - (x >> 1);
}
static void map_rehash(map_t* map) {
map_t old = *map;
map->size <<= 1;
map->hashes = malloc(2 * map->size * sizeof(uint64_t));
map->values = map->hashes + map->size;
lovrAssert(map->size && map->hashes, "Out of memory");
memset(map->hashes, 0xff, 2 * map->size * sizeof(uint64_t));
if (old.hashes) {
uint64_t mask = map->size - 1;
for (uint32_t i = 0; i < old.size; i++) {
if (old.hashes[i] != MAP_NIL) {
uint64_t index = old.hashes[i] & mask;
while (map->hashes[index] != MAP_NIL) {
index = (index + 1) & mask;
}
map->hashes[index] = old.hashes[i];
map->values[index] = old.values[i];
}
}
free(old.hashes);
}
}
static inline uint64_t map_find(map_t* map, uint64_t hash) {
uint64_t mask = map->size - 1;
uint64_t h = hash & mask;
while (map->hashes[h] != hash && map->hashes[h] != MAP_NIL) {
h = (h + 1) & mask;
}
return h;
}
void map_init(map_t* map, uint32_t n) {
map->size = prevpo2(n) + !n;
map->used = 0;
map->hashes = NULL;
map_rehash(map);
}
void map_free(map_t* map) {
free(map->hashes);
}
uint64_t map_get(map_t* map, uint64_t hash) {
return map->values[map_find(map, hash)];
}
void map_set(map_t* map, uint64_t hash, uint64_t value) {
if (map->used >= (map->size >> 1) + (map->size >> 2)) {
map_rehash(map);
}
uint64_t h = map_find(map, hash);
map->used += map->hashes[h] == MAP_NIL;
map->hashes[h] = hash;
map->values[h] = value;
}
void map_remove(map_t* map, uint64_t hash) {
uint64_t h = map_find(map, hash);
if (map->hashes[h] == MAP_NIL) {
return;
}
uint64_t mask = map->size - 1;
uint64_t i = h;
do {
i = (i + 1) & mask;
uint64_t x = map->hashes[i] & mask;
// Removing a key from an open-addressed hash table is complicated
if ((i > h && (x <= h || x > i)) || (i < h && (x <= h && x > i))) {
map->hashes[h] = map->hashes[i];
map->values[h] = map->values[i];
h = i;
}
} while (map->hashes[i] != MAP_NIL);
map->hashes[i] = MAP_NIL;
map->values[i] = MAP_NIL;
map->used--;
}

View File

@ -1,18 +0,0 @@
#include <stdint.h>
#pragma once
#define MAP_NIL UINT64_MAX
typedef struct {
uint32_t size;
uint32_t used;
uint64_t* hashes;
uint64_t* values;
} map_t;
void map_init(map_t* map, uint32_t n);
void map_free(map_t* map);
uint64_t map_get(map_t* map, uint64_t hash);
void map_set(map_t* map, uint64_t hash, uint64_t value);
void map_remove(map_t* map, uint64_t hash);

View File

@ -1,4 +1,3 @@
#include "core/map.h"
#include "util.h"
#include <stdbool.h>
#include <stdint.h>

View File

@ -2,7 +2,6 @@
#include "data/blob.h"
#include "data/image.h"
#include "core/maf.h"
#include "core/map.h"
#include "util.h"
#include <stdlib.h>
#include <float.h>

View File

@ -1,6 +1,5 @@
#include "filesystem/filesystem.h"
#include "core/fs.h"
#include "core/map.h"
#include "core/os.h"
#include "util.h"
#include "core/zip.h"

View File

@ -3,7 +3,6 @@
#include "graphics/texture.h"
#include "data/rasterizer.h"
#include "data/image.h"
#include "core/map.h"
#include <string.h>
#include <stdlib.h>

View File

@ -1,6 +1,5 @@
#include "thread/thread.h"
#include "thread/channel.h"
#include "core/map.h"
#include "util.h"
#include <stdlib.h>
#include <string.h>

View File

@ -1,4 +1,5 @@
#include "util.h"
#include <string.h>
#include <stdlib.h>
#include <stdatomic.h>
@ -63,6 +64,103 @@ void* arr_alloc(void* data, size_t size) {
}
}
// Hashmap
static uint32_t prevpo2(uint32_t x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x - (x >> 1);
}
static void map_rehash(map_t* map) {
map_t old = *map;
map->size <<= 1;
map->hashes = malloc(2 * map->size * sizeof(uint64_t));
map->values = map->hashes + map->size;
lovrAssert(map->size && map->hashes, "Out of memory");
memset(map->hashes, 0xff, 2 * map->size * sizeof(uint64_t));
if (old.hashes) {
uint64_t mask = map->size - 1;
for (uint32_t i = 0; i < old.size; i++) {
if (old.hashes[i] != MAP_NIL) {
uint64_t index = old.hashes[i] & mask;
while (map->hashes[index] != MAP_NIL) {
index = (index + 1) & mask;
}
map->hashes[index] = old.hashes[i];
map->values[index] = old.values[i];
}
}
free(old.hashes);
}
}
static inline uint64_t map_find(map_t* map, uint64_t hash) {
uint64_t mask = map->size - 1;
uint64_t h = hash & mask;
while (map->hashes[h] != hash && map->hashes[h] != MAP_NIL) {
h = (h + 1) & mask;
}
return h;
}
void map_init(map_t* map, uint32_t n) {
map->size = prevpo2(n) + !n;
map->used = 0;
map->hashes = NULL;
map_rehash(map);
}
void map_free(map_t* map) {
free(map->hashes);
}
uint64_t map_get(map_t* map, uint64_t hash) {
return map->values[map_find(map, hash)];
}
void map_set(map_t* map, uint64_t hash, uint64_t value) {
if (map->used >= (map->size >> 1) + (map->size >> 2)) {
map_rehash(map);
}
uint64_t h = map_find(map, hash);
map->used += map->hashes[h] == MAP_NIL;
map->hashes[h] = hash;
map->values[h] = value;
}
void map_remove(map_t* map, uint64_t hash) {
uint64_t h = map_find(map, hash);
if (map->hashes[h] == MAP_NIL) {
return;
}
uint64_t mask = map->size - 1;
uint64_t i = h;
do {
i = (i + 1) & mask;
uint64_t x = map->hashes[i] & mask;
// Removing a key from an open-addressed hash table is complicated
if ((i > h && (x <= h || x > i)) || (i < h && (x <= h && x > i))) {
map->hashes[h] = map->hashes[i];
map->values[h] = map->values[i];
h = i;
}
} while (map->hashes[i] != MAP_NIL);
map->hashes[i] = MAP_NIL;
map->values[i] = MAP_NIL;
map->used--;
}
// UTF-8
// https://github.com/starwing/luautf8
size_t utf8_decode(const char *s, const char *e, unsigned *pch) {

View File

@ -83,6 +83,22 @@ static inline void _arr_reserve(void** data, size_t n, size_t* capacity, size_t
lovrAssert(*data, "Out of memory");
}
// Hashmap
typedef struct {
uint64_t* hashes;
uint64_t* values;
uint32_t size;
uint32_t used;
} map_t;
#define MAP_NIL UINT64_MAX
void map_init(map_t* map, uint32_t n);
void map_free(map_t* map);
uint64_t map_get(map_t* map, uint64_t hash);
void map_set(map_t* map, uint64_t hash, uint64_t value);
void map_remove(map_t* map, uint64_t hash);
// UTF-8
size_t utf8_decode(const char *s, const char *e, unsigned *pch);
void utf8_encode(uint32_t codepoint, char str[4]);