mirror of https://github.com/bjornbytes/lovr.git
mv map util;
This commit is contained in:
parent
faa42ee38b
commit
5d271de91a
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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>
|
||||
|
|
100
src/core/map.c
100
src/core/map.c
|
@ -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--;
|
||||
}
|
|
@ -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);
|
|
@ -1,4 +1,3 @@
|
|||
#include "core/map.h"
|
||||
#include "util.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
98
src/util.c
98
src/util.c
|
@ -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) {
|
||||
|
|
16
src/util.h
16
src/util.h
|
@ -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]);
|
||||
|
|
Loading…
Reference in New Issue