use pread/pwrite instead of stdio API
This commit is contained in:
parent
ace7232d93
commit
8fc79dd372
135
idx.c
135
idx.c
|
@ -3,68 +3,63 @@
|
|||
#include "y16t_internal.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static __attribute__((pure))
|
||||
uint32_t y16t_table_at(const uint8_t x, const uint8_t y)
|
||||
uint32_t y16t_table_at(const y16t_idx_t idx, const uint8_t x, const uint8_t y)
|
||||
{
|
||||
return y16t_hilbert_xy2d(1 << 16, x, y) << 2;
|
||||
return (idx.offset << 10)
|
||||
| (y16t_hilbert_xy2d(1 << 16, x, y) << 2);
|
||||
}
|
||||
|
||||
static __attribute__((pure))
|
||||
int y16t_idx_hret(const int tmp)
|
||||
{
|
||||
if(tmp == 4) {
|
||||
return 0;
|
||||
} else if(tmp < 0) {
|
||||
return tmp;
|
||||
} else {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
int y16t_idx_lookup(
|
||||
FILE *fh,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint32_t *result
|
||||
y16t_idx_t idx,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint32_t *result
|
||||
) {
|
||||
const long key = y16t_table_at(x, y);
|
||||
|
||||
if(key && fseek(fh, key, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
if(fread(result, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
*result = ntohl(*result);
|
||||
if(fseek(fh, -key - 4, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
const off_t key = y16t_table_at(idx, x, y);
|
||||
const int tmp = y16t_idx_hret(y16t_pread_all(idx.fd, result, 4, key));
|
||||
if(tmp >= 0) *result = ntohl(*result);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
int y16t_idx_update(
|
||||
FILE *fh,
|
||||
y16t_idx_t idx,
|
||||
const uint8_t x,
|
||||
const uint8_t y,
|
||||
const uint32_t newval
|
||||
) {
|
||||
const long key = y16t_table_at(x, y);
|
||||
const off_t key = y16t_table_at(idx, x, y);
|
||||
const uint32_t odval = htonl(newval);
|
||||
|
||||
if(key && fseek(fh, key, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
if(fwrite(&odval, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
if(fseek(fh, -key - 4, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
return y16t_idx_hret(y16t_pwrite_all(idx.fd, &odval, 4, key));
|
||||
}
|
||||
|
||||
int y16t_idx_get_or_insert(
|
||||
FILE *fh,
|
||||
y16t_idx_t idx,
|
||||
const uint8_t x,
|
||||
const uint8_t y,
|
||||
uint32_t *value,
|
||||
uint32_t (*palloc)(void*),
|
||||
void *context
|
||||
uint32_t *value,
|
||||
uint32_t (*palloc)(void*),
|
||||
void *context
|
||||
) {
|
||||
const long key = y16t_table_at(x, y);
|
||||
|
||||
if(key && fseek(fh, key, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
const long key = y16t_table_at(idx, x, y);
|
||||
uint32_t value_tmp = 0;
|
||||
|
||||
if(fread(&value_tmp, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
int tmp = y16t_idx_hret(y16t_pread_all(idx.fd, &value_tmp, 4, key));
|
||||
if(tmp < 0)
|
||||
return tmp;
|
||||
|
||||
if(!value_tmp) {
|
||||
// allocate new entry
|
||||
|
@ -72,78 +67,50 @@ int y16t_idx_get_or_insert(
|
|||
if(!value_tmp)
|
||||
return -ENOMEM;
|
||||
value_tmp = htonl(value_tmp);
|
||||
if(fseek(fh, -4, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
if(fwrite(&value_tmp, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
tmp = y16t_idx_hret(y16t_pwrite_all(idx.fd, &value_tmp, 4, key));
|
||||
}
|
||||
|
||||
*value = ntohl(value_tmp);
|
||||
|
||||
if(fseek(fh, -key - 4, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static int y16t_idx_foreach_inner(
|
||||
FILE *fh,
|
||||
long *offset,
|
||||
y16t_idx_t idx,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
) {
|
||||
const uint32_t key = y16t_table_at(x, y);
|
||||
const long delta = ((long)key) - *offset;
|
||||
if(delta && fseek(fh, delta, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
*offset = key + 4;
|
||||
uint32_t value = 0;
|
||||
if(fread(&value, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
const int tmp = callback(ntohl(value), context);
|
||||
if(tmp) {
|
||||
fseek(fh, -*offset, SEEK_CUR);
|
||||
*offset = 0;
|
||||
}
|
||||
return tmp;
|
||||
int tmp = y16t_idx_lookup(idx, x, y, &value);
|
||||
if(tmp < 0) return tmp;
|
||||
return callback(ntohl(value), context);
|
||||
}
|
||||
|
||||
int y16t_idx_foreach_x(
|
||||
FILE *fh,
|
||||
uint8_t y,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
y16t_idx_t idx,
|
||||
uint8_t y,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
) {
|
||||
long offset = 0;
|
||||
|
||||
for (uint16_t x = 0; x < 0xff; ++x) {
|
||||
const int tmp = y16t_idx_foreach_inner(fh, &offset, x, y, callback, context);
|
||||
const int tmp = y16t_idx_foreach_inner(idx, x, y, callback, context);
|
||||
if(tmp) return tmp;
|
||||
}
|
||||
|
||||
if(offset && fseek(fh, -offset, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int y16t_idx_foreach_y(
|
||||
FILE *fh,
|
||||
uint8_t x,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
y16t_idx_t idx,
|
||||
uint8_t x,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
) {
|
||||
long offset = 0;
|
||||
|
||||
for (uint16_t y = 0; y < 0xff; ++y) {
|
||||
const int tmp = y16t_idx_foreach_inner(fh, &offset, x, y, callback, context);
|
||||
const int tmp = y16t_idx_foreach_inner(idx, x, y, callback, context);
|
||||
if(tmp) return tmp;
|
||||
}
|
||||
|
||||
if(offset && fseek(fh, -offset, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
15
meson.build
15
meson.build
|
@ -6,17 +6,26 @@ project('y16t 16bit-field quad tree library', 'c',
|
|||
|
||||
install_headers('y16t.h')
|
||||
|
||||
c_base_args = [
|
||||
'-fno-plt',
|
||||
'-fno-unwind-tables',
|
||||
'-fno-exceptions',
|
||||
'-Werror=return-type',
|
||||
'-Werror=implicit-function-declaration',
|
||||
'-Werror=incompatible-pointer-types-discards-qualifiers',
|
||||
'-D_XOPEN_SOURCE=500']
|
||||
|
||||
liby16t = shared_library('y16t',
|
||||
files('hilbert.c', 'idx.c'),
|
||||
files('hilbert.c', 'idx.c', 'pall.c'),
|
||||
version : '0.0.0',
|
||||
c_args : ['-fno-plt', '-fno-unwind-tables', '-fno-exceptions', '-Werror=return-type'],
|
||||
c_args : [c_base_args],
|
||||
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'],
|
||||
c_args : [c_base_args],
|
||||
include_directories : include_directories('.'),
|
||||
install : true
|
||||
)
|
||||
|
|
56
pall.c
Normal file
56
pall.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
#include "y16t_internal.h"
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
__attribute__((nonnull))
|
||||
static ssize_t y16t_pall_hret(const ssize_t tmp, size_t *dnb)
|
||||
{
|
||||
if(tmp > 0) {
|
||||
*dnb += tmp;
|
||||
return tmp;
|
||||
} else if(!tmp) {
|
||||
return -EIO;
|
||||
} else {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t y16t_pread_all(const int fd, void *buf, size_t nbyte, off_t offset)
|
||||
{
|
||||
size_t dnb = 0;
|
||||
while(nbyte) {
|
||||
const ssize_t tmp = y16t_pall_hret(pread(
|
||||
fd,
|
||||
buf + dnb,
|
||||
nbyte - dnb,
|
||||
offset + dnb), &dnb);
|
||||
switch(tmp) {
|
||||
case -EINTR:
|
||||
continue;
|
||||
default:
|
||||
if(tmp > 0) continue;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return (ssize_t)dnb;
|
||||
}
|
||||
|
||||
ssize_t y16t_pwrite_all(const int fd, const void *buf, size_t nbyte, off_t offset)
|
||||
{
|
||||
size_t dnb = 0;
|
||||
while(nbyte) {
|
||||
const ssize_t tmp = y16t_pall_hret(pwrite(
|
||||
fd,
|
||||
buf + dnb,
|
||||
nbyte - dnb,
|
||||
offset + dnb), &dnb);
|
||||
switch(tmp) {
|
||||
case -EINTR:
|
||||
continue;
|
||||
default:
|
||||
if(tmp > 0) continue;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return (ssize_t)dnb;
|
||||
}
|
36
y16t.h
36
y16t.h
|
@ -2,7 +2,12 @@
|
|||
#pragma once
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
// offset is in 1KiB units
|
||||
size_t offset;
|
||||
} y16t_idx_t;
|
||||
|
||||
// try to lookup the given coordinates,
|
||||
// and return the corresponding location via `result`.
|
||||
|
@ -10,24 +15,23 @@
|
|||
// returns a negative errno number in case of failure
|
||||
__attribute__((nonnull))
|
||||
int y16t_idx_lookup(
|
||||
FILE *fh,
|
||||
y16t_idx_t idx,
|
||||
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
|
||||
y16t_idx_t idx,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint32_t newval
|
||||
);
|
||||
|
||||
// insert a table entry if it doesn't already exist
|
||||
int y16t_idx_get_or_insert(
|
||||
FILE *fh,
|
||||
y16t_idx_t idx,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint32_t *value,
|
||||
|
@ -37,15 +41,15 @@ int y16t_idx_get_or_insert(
|
|||
|
||||
// iterate over columns or rows
|
||||
int y16t_idx_foreach_x(
|
||||
FILE *fh,
|
||||
uint8_t y,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
y16t_idx_t idx,
|
||||
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
|
||||
y16t_idx_t idx,
|
||||
uint8_t χ,
|
||||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
#pragma once
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
// conversion between hilbert curve distance and x,y values
|
||||
|
@ -8,3 +9,8 @@ __attribute__((pure))
|
|||
uint32_t y16t_hilbert_xy2d(uint32_t n, uint32_t x, uint32_t y);
|
||||
|
||||
void y16t_hilbert_d2xy(uint32_t n, uint32_t d, uint32_t *x, uint32_t *y);
|
||||
|
||||
// handling of resumption of pread/pwrite calls
|
||||
|
||||
ssize_t y16t_pread_all(int fd, void *buf, size_t nbyte, off_t offset);
|
||||
ssize_t y16t_pwrite_all(int fd, const void *buf, size_t nbyte, off_t offset);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "y16t.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int printall_fecb(uint32_t x, void* ctx)
|
||||
{
|
||||
|
@ -15,18 +16,19 @@ int main(int argc, char *argv[])
|
|||
return -1;
|
||||
}
|
||||
|
||||
FILE *fh = fopen(argv[1], "r");
|
||||
|
||||
if(!fh) {
|
||||
int fd = open(argv[1], O_RDONLY);
|
||||
if(fd < 0) {
|
||||
perror("open");
|
||||
fprintf(stderr, "ERROR: unable to open file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t value = atoi(argv[3]);
|
||||
const y16t_idx_t idx = { fd, 0 };
|
||||
|
||||
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);
|
||||
case 'x': return y16t_idx_foreach_x(idx, value, printall_fecb, 0);
|
||||
case 'y': return y16t_idx_foreach_y(idx, value, printall_fecb, 0);
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue