just use a single 16bit index
This commit is contained in:
parent
bf9048443b
commit
4e5fd39cc9
12
meson.build
12
meson.build
|
@ -1,6 +1,6 @@
|
|||
project('y16t 16-field quad tree library', 'c',
|
||||
default_options : ['c_std=c17'],
|
||||
version : '0.0.0'
|
||||
version : '0.0.0',
|
||||
license : 'Apache-2.0',
|
||||
meson_version : '>=0.50')
|
||||
|
||||
|
@ -10,9 +10,17 @@ liby16t = shared_library('y16t',
|
|||
files('y16t.c'),
|
||||
version : '0.0.0',
|
||||
c_args : ['-fno-plt', '-fno-unwind-tables', '-fno-exceptions', '-Werror=return-type'],
|
||||
include_directories : include_directories('.')
|
||||
include_directories : include_directories('.'),
|
||||
install : true)
|
||||
|
||||
executable('y16t-printall',
|
||||
files('y16t_printall.c'),
|
||||
link_with : [liby16t],
|
||||
c_args : ['-fno-plt', '-fno-unwind-tables', '-fno-exceptions', '-Werror=return-type'],
|
||||
include_directories : include_directories('.'),
|
||||
install : true
|
||||
)
|
||||
|
||||
pkg_mod = import('pkgconfig')
|
||||
pkg_mod.generate(
|
||||
libraries : [liby16t],
|
||||
|
|
101
y16t.c
101
y16t.c
|
@ -1,37 +1,86 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
#include "y16t.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
|
||||
// conversion to ις-points interleaved coordinates
|
||||
static __attribute__((pure))
|
||||
uint8_t y16t_loc2blk_coords(
|
||||
const y16t_location_t loc, const uint32_t offset
|
||||
) {
|
||||
const uint32_t byteoffset = offset >> 1;
|
||||
const uint8_t shiftval = 4 * (1 - offset & 1);
|
||||
const uint8_t xres = (loc.x[byteoffset] >> shiftval) & 15;
|
||||
const uint8_t yres = (loc.y[byteoffset] >> shiftval) & 15;
|
||||
return (xres << 4) | yres;
|
||||
uint16_t y16t_interleave2(const uint8_t x, const uint8_t y)
|
||||
{
|
||||
return
|
||||
((uint16_t)((x & 0x55) | (y & 0xaa)) << 8)
|
||||
|
|
||||
(uint16_t)((x & 0xaa) | (y & 0x55))
|
||||
;
|
||||
}
|
||||
|
||||
void y16t_lookup(
|
||||
y16t_lookup_t * ret,
|
||||
const uint32_t * data,
|
||||
const size_t datalen,
|
||||
const y16t_location_t * loc
|
||||
) {
|
||||
const size_t datalen_blks = datalen >> 8;
|
||||
const y16t_location_t loc_ = *loc;
|
||||
size_t datoffset = ret->datoffset;
|
||||
static __attribute__((pure))
|
||||
uint32_t y16t_table_at(const uint8_t x, const uint8_t y)
|
||||
{
|
||||
return ((uint32_t)y16t_interleave2(x, y)) << 2;
|
||||
}
|
||||
|
||||
for ( ; /* bounds checks */ ret->inpoffset < loc_.xylen && datoffset < datalen_blks; ) {
|
||||
datoffset = ntohl(data[(datoffset << 8) | y16t_loc2blk_coords(loc_, ret->inpoffset)]);
|
||||
ret->inpoffset += 1;
|
||||
if(0 == datoffset) {
|
||||
// NULL pointer
|
||||
break;
|
||||
}
|
||||
int y16t_idx_lookup(
|
||||
FILE *fh,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint32_t *result
|
||||
) {
|
||||
const uint32_t key = y16t_table_at(x, y);
|
||||
|
||||
if(fseek(fh, (long)key, SEEK_SET) == -1)
|
||||
return -EIO;
|
||||
if(fread(result, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int y16t_idx_update(
|
||||
FILE *fh,
|
||||
const uint8_t x,
|
||||
const uint8_t y,
|
||||
const uint32_t newval
|
||||
) {
|
||||
const uint32_t key = y16t_table_at(x, y);
|
||||
|
||||
if(fseek(fh, (long)key, SEEK_SET) == -1)
|
||||
return -EIO;
|
||||
|
||||
if(fwrite(&newval, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int y16t_idx_foreach_x(
|
||||
FILE *fh,
|
||||
uint8_t y,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
) {
|
||||
for (uint16_t x = 0; x < 0xff; ++x) {
|
||||
uint32_t value = 0;
|
||||
int tmp = y16t_idx_lookup(fh, x, y, &value);
|
||||
if(tmp != 0) return tmp;
|
||||
tmp = callback(value, context);
|
||||
if(tmp != 0) return tmp;
|
||||
}
|
||||
|
||||
ret->datoffset = datoffset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int y16t_idx_foreach_y(
|
||||
FILE *fh,
|
||||
uint8_t x,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
) {
|
||||
for (uint16_t y = 0; y < 0xff; ++y) {
|
||||
uint32_t value = 0;
|
||||
int tmp = y16t_idx_lookup(fh, x, y, &value);
|
||||
if(tmp != 0) return tmp;
|
||||
tmp = callback(value, context);
|
||||
if(tmp != 0) return tmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
63
y16t.h
63
y16t.h
|
@ -2,33 +2,40 @@
|
|||
#pragma once
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t *x;
|
||||
uint8_t *y;
|
||||
// x and y should have the same length, and xylen = bytescount * 2
|
||||
uint32_t xylen;
|
||||
} y16t_location_t;
|
||||
|
||||
typedef struct {
|
||||
// the offset indicates how far the lookup could traverse the tree
|
||||
uint32_t inpoffset;
|
||||
|
||||
// the final data pointer, it doesn't have to be aligned to block boundaries
|
||||
// if it ends up at the starting point, but the offset isn't 0,
|
||||
// then a NULL pointer was hit
|
||||
size_t datoffset;
|
||||
} y16t_lookup_t;
|
||||
|
||||
// @param ret ... the starting point; gets updated to the latest via the given path
|
||||
// reachable point
|
||||
// @param data ... a pointer to a mmap-ed file. we convert pointers inside of the file
|
||||
// from network byte order to host byte order before following them.
|
||||
// @param datalen ... the length of the block that data points to, in 4 byte units (= file size in bytes / 4)
|
||||
__attribute__((pure, nonnull))
|
||||
void y16t_lookup(
|
||||
y16t_lookup_t * ret,
|
||||
const uint32_t * data,
|
||||
const size_t datalen,
|
||||
const y16t_location_t * loc
|
||||
// try to lookup the given coordinates, and return the corresponding location
|
||||
// via `result`.
|
||||
// the file given as `fh` is expected to be at least 256KiB large
|
||||
// returns a negative errno number in case of failure
|
||||
__attribute__((nonnull))
|
||||
int y16t_idx_lookup(
|
||||
FILE *fh,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint32_t *result
|
||||
);
|
||||
|
||||
// update a table entry.
|
||||
__attribute__((nonnull))
|
||||
int y16t_idx_update(
|
||||
FILE *fh,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint32_t newval
|
||||
);
|
||||
|
||||
// iterate over columns or rows
|
||||
int y16t_idx_foreach_x(
|
||||
FILE *fh,
|
||||
uint8_t y,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
);
|
||||
|
||||
int y16t_idx_foreach_y(
|
||||
FILE *fh,
|
||||
uint8_t χ,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
);
|
||||
|
|
32
y16t_printall.c
Normal file
32
y16t_printall.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include "y16t.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int printall_fecb(uint32_t x, void*)
|
||||
{
|
||||
printf("%08x\n", x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc < 4) {
|
||||
fprintf(stderr, "USAGE: y16t-print FILE x|y VALUE\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *fh = fopen(argv[1], "r");
|
||||
|
||||
if(!fh) {
|
||||
fprintf(stderr, "ERROR: unable to open file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t value = atoi(argv[3]);
|
||||
|
||||
switch(argv[2][0]) {
|
||||
case 'x': return y16t_idx_foreach_x(fh, value, printall_fecb, 0);
|
||||
case 'y': return y16t_idx_foreach_y(fh, value, printall_fecb, 0);
|
||||
default: return -1;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue