diff options
| author | 2023-10-10 20:59:07 -0400 | |
|---|---|---|
| committer | 2023-10-10 20:59:07 -0400 | |
| commit | a723efcc67b6c14ff0dd1efd1ba88596e959daaa (patch) | |
| tree | 45384ce34e9601533fdc5bfbbdaf1b63ea7f1310 /src/util | |
| download | libnaunet-a723efcc67b6c14ff0dd1efd1ba88596e959daaa.tar.gz libnaunet-a723efcc67b6c14ff0dd1efd1ba88596e959daaa.tar.bz2 libnaunet-a723efcc67b6c14ff0dd1efd1ba88596e959daaa.zip | |
Add libakiyo
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/util')
| -rw-r--r-- | src/util/buffer.c | 42 | ||||
| -rw-r--r-- | src/util/buffer.h | 17 | ||||
| -rw-r--r-- | src/util/error.c | 7 | ||||
| -rw-r--r-- | src/util/error.h | 21 | ||||
| -rw-r--r-- | src/util/file/file.c | 0 | ||||
| -rw-r--r-- | src/util/file/file.h | 82 | ||||
| -rw-r--r-- | src/util/file/file_linux.c | 203 | ||||
| -rw-r--r-- | src/util/file/file_stdio.c | 100 | ||||
| -rw-r--r-- | src/util/file/util.c | 25 | ||||
| -rw-r--r-- | src/util/packet.c | 104 | ||||
| -rw-r--r-- | src/util/packet.h | 65 | ||||
| -rw-r--r-- | src/util/thread/thread.h | 66 | ||||
| -rw-r--r-- | src/util/thread/thread_linux.c | 86 | ||||
| -rw-r--r-- | src/util/thread/thread_windows.c | 81 | ||||
| -rw-r--r-- | src/util/timer/timer.h | 6 | ||||
| -rw-r--r-- | src/util/timer/timer_linux.c | 17 | ||||
| -rw-r--r-- | src/util/timer/timer_windows.c | 39 |
17 files changed, 961 insertions, 0 deletions
diff --git a/src/util/buffer.c b/src/util/buffer.c new file mode 100644 index 0000000..26e242c --- /dev/null +++ b/src/util/buffer.c @@ -0,0 +1,42 @@ +#include "buffer.h" + +#define INITIAL_SIZE 128 + +void aki_buffer_ensure_size(struct aki_buffer *buf, size_t size) +{ + if (buf->alloc >= size) return; + if (size < INITIAL_SIZE) buf->alloc = INITIAL_SIZE; + else buf->alloc = al_next_power_of_two(size); + buf->data = buf->data ? al_realloc(buf->data, buf->alloc) : al_malloc(buf->alloc); +} + +void aki_buffer_init(struct aki_buffer *buf) +{ + buf->data = NULL; + buf->size = 0; + buf->alloc = 0; +} + +void aki_buffer_write(struct aki_buffer *buf, void *data, size_t index, size_t size) +{ + size_t reach = index + size; + aki_buffer_ensure_size(buf, reach); + if (reach > buf->size) buf->size = reach; + al_memcpy(&buf->data[index], data, size); +} + +u8 *aki_buffer_get_ptr(struct aki_buffer *buf, size_t index) +{ + return &buf->data[index]; +} + +void aki_buffer_read(struct aki_buffer *buf, void *ptr, size_t index, size_t size) +{ + al_assert(index + size <= buf->size); + al_memcpy(ptr, &buf->data[index], size); +} + +void aki_buffer_free(struct aki_buffer *buf) +{ + if (buf->data && buf->alloc > 0) al_free(buf->data); +} diff --git a/src/util/buffer.h b/src/util/buffer.h new file mode 100644 index 0000000..3c40b3a --- /dev/null +++ b/src/util/buffer.h @@ -0,0 +1,17 @@ +#pragma once + +#include <al/types.h> +#include <al/lib.h> + +struct aki_buffer { + u8 *data; + size_t size; + size_t alloc; +}; + +void aki_buffer_init(struct aki_buffer *buf); +void aki_buffer_ensure_size(struct aki_buffer *buf, size_t size); +void aki_buffer_write(struct aki_buffer *buf, void *data, size_t index, size_t size); +u8 *aki_buffer_get_ptr(struct aki_buffer *buf, size_t index); +void aki_buffer_read(struct aki_buffer *buf, void *ptr, size_t index, size_t size); +void aki_buffer_free(struct aki_buffer *buf); diff --git a/src/util/error.c b/src/util/error.c new file mode 100644 index 0000000..f055416 --- /dev/null +++ b/src/util/error.c @@ -0,0 +1,7 @@ +#include "error.h" + +#ifndef _WIN32 +__thread char errorbuf[ERROR_STR_MAXLEN]; +#else +__declspec(thread) char errorbuf[ERROR_STR_MAXLEN]; +#endif diff --git a/src/util/error.h b/src/util/error.h new file mode 100644 index 0000000..d014faa --- /dev/null +++ b/src/util/error.h @@ -0,0 +1,21 @@ +#include <al/lib.h> + +#include <errno.h> + +#define ERROR_STR_MAXLEN 94 + +#ifndef _WIN32 +extern __thread char errorbuf[ERROR_STR_MAXLEN]; +#else +extern __declspec(thread) char errorbuf[ERROR_STR_MAXLEN]; +#endif + +static inline char *aki_strerror(s32 errnum) +{ +#ifndef _WIN32 + strerror_r(errnum, errorbuf, ERROR_STR_MAXLEN); +#else + strerror_s(errorbuf, ERROR_STR_MAXLEN, errnum); +#endif + return errorbuf; +} diff --git a/src/util/file/file.c b/src/util/file/file.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/util/file/file.c diff --git a/src/util/file/file.h b/src/util/file/file.h new file mode 100644 index 0000000..465d76a --- /dev/null +++ b/src/util/file/file.h @@ -0,0 +1,82 @@ +#pragma once + +#ifdef AKIYO_FILE_STDIO_COMPAT +#include <stdio.h> +#else +#ifndef _WIN32 +#include <dirent.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/stat.h> +#include <sys/mman.h> +#endif +#endif + +#include <al/str.h> + +enum { + AKI_ENTRY_FILE = 0, + AKI_ENTRY_DIR, + AKI_ENTRY_OTHER +}; + +struct aki_file { +#ifdef AKIYO_FILE_STDIO_COMPAT + FILE *file; +#else +#ifndef _WIN32 + s32 fd; +#else + // WINDOWS +#endif +#endif + size_t filesize; +}; + +struct aki_dir { +#ifdef AKIYO_FILE_STDIO_COMPAT +#else +#ifndef _WIN32 + DIR *dir; +#else + // WINDOWS +#endif +#endif + str path; +}; + +struct aki_dir_entry { + u8 type; +#ifdef AKIYO_FILE_STDIO_COMPAT +#else +#ifndef _WIN32 + struct dirent *entry; +#else + // WINDOWS +#endif +#endif + str name; + str path; +}; + +bool aki_file_open(struct aki_file *file, str *path, bool create); +bool aki_file_exists(str *path); +bool aki_file_truncate(struct aki_file *file, off_t size); +off_t aki_file_seek(struct aki_file *file, off_t offset, s32 whence); +size_t aki_file_get_filesize(struct aki_file *file); +bool aki_file_write(struct aki_file *file, void *buf, size_t size); +bool aki_file_read(struct aki_file *file, void *buf, size_t size); +s32 aki_file_read_as_str(struct aki_file *file, str *out); +s32 aki_file_read_as_c_str(struct aki_file *file, char **out); +void *aki_file_mmap(struct aki_file *file); +void *aki_file_mremap(struct aki_file *file, size_t size, void *old_map); +void aki_file_munmap(struct aki_file *file, void *map); +void aki_file_close(struct aki_file *file); + +bool aki_dir_open(struct aki_dir *dir, str *path); +void aki_dir_close(struct aki_dir *dir); +bool aki_dir_exists(str *path); +bool aki_dir_create(str *path); +bool aki_dir_read(struct aki_dir *dir, struct aki_dir_entry *entry); +void aki_dir_entry_free(struct aki_dir_entry *entry); diff --git a/src/util/file/file_linux.c b/src/util/file/file_linux.c new file mode 100644 index 0000000..97e9688 --- /dev/null +++ b/src/util/file/file_linux.c @@ -0,0 +1,203 @@ +#include <sys/mman.h> +#include <al/log.h> + +#include "../error.h" + +#include "file.h" + +bool aki_file_open(struct aki_file *file, str *path, bool create) +{ + char *c_str = al_str_to_c_str(path); + s32 flags = O_RDWR; + if (create) flags |= O_CREAT; + file->fd = open(c_str, flags, 0666); + al_free(c_str); + if (file->fd == -1) { + al_log_error("file", "open(%.*s) failed (%s).", AL_STR_PRINTF(path), aki_strerror(errno)); + return false; + } + struct stat sb; + s32 res = fstat(file->fd, &sb); + if (res == -1) { + al_log_error("file", "fstat() failed (%s).", aki_strerror(errno)); + close(file->fd); + return false; + } + file->filesize = sb.st_size; + return true; +} + +bool aki_file_exists(str *path) +{ + char *c_str = al_str_to_c_str(path); + s32 ret = access(c_str, F_OK); + al_free(c_str); + if (ret != 0) { + al_log_error("file", "access(%.*s, F_OK) failed (%s).", AL_STR_PRINTF(path), aki_strerror(errno)); + } + return ret == 0; +} + +off_t aki_file_seek(struct aki_file *file, off_t offset, s32 whence) +{ + off_t res = lseek(file->fd, offset, whence); + if (res == (off_t)-1) { + al_log_error("file", "lseek(%jd, %d) failed (%s).", (intmax_t)offset, whence, aki_strerror(errno)); + } + return res; +} + +bool aki_file_truncate(struct aki_file *file, off_t size) +{ + s32 ret = ftruncate(file->fd, size); + if (ret != 0) { + al_log_error("file", "ftruncate(%jd) failed (%s).", (intmax_t)size, aki_strerror(errno)); + return false; + } + file->filesize = size; + return true; +} + +size_t aki_file_get_filesize(struct aki_file *file) +{ + return file->filesize; +} + +#define file_io_loop(call, fail_case) \ + size_t bc = 0; \ + ssize_t res; \ + do { \ + res = call(file->fd, buf, size - bc); \ + if (fail_case) { \ + al_log_error("file", ""#call"() failed (%s).", aki_strerror(errno)); \ + return false; \ + } \ + bc += res; \ + } while (bc < size); \ + return true + +bool aki_file_write(struct aki_file *file, void *buf, size_t size) +{ + file_io_loop(write, (res == -1)); +} + +bool aki_file_read(struct aki_file *file, void *buf, size_t size) +{ + file_io_loop(read, (res == -1)); +} + +void *aki_file_mmap(struct aki_file *file) +{ + void *map = mmap(NULL, file->filesize, PROT_READ | PROT_WRITE, MAP_SHARED, file->fd, 0L); + if (map == MAP_FAILED) { + al_log_error("file", "mmap() failed (%s).", aki_strerror(errno)); + return NULL; + } + return map; +} + +void *aki_file_mremap(struct aki_file *file, size_t size, void *old_map) +{ + printf("old_size: %zu, new_size: %zu\n", file->filesize, size); + void *map = mremap(old_map, file->filesize, size, MREMAP_MAYMOVE); + if (map == MAP_FAILED) { + al_log_error("file", "mremap(%p, %zu, %zu) failed (%s).", old_map, + file->filesize, size, aki_strerror(errno)); + return NULL; + } + return map; +} + +void aki_file_munmap(struct aki_file *file, void *map) +{ + s32 ret = munmap(map, file->filesize); + if (ret != 0) { + al_log_error("file", "munmap(%p, %zu) failed (%s).", map, file->filesize, aki_strerror(errno)); + } +} + +void aki_file_close(struct aki_file *file) +{ + close(file->fd); +} + +bool aki_dir_open(struct aki_dir *dir, str *path) +{ + char *c_str = al_str_to_c_str(path); + dir->dir = opendir(c_str); + al_free(c_str); + if (!dir->dir) { + al_log_error("file", "opendir(%.*s) failed (%s).", AL_STR_PRINTF(path), aki_strerror(errno)); + return false; + } + al_str_clone(&dir->path, path); + return true; +} + +void aki_dir_close(struct aki_dir *dir) +{ + al_str_free(&dir->path); + closedir(dir->dir); +} + +bool aki_dir_exists(str *path) +{ + struct aki_dir dir; + char *c_str = al_str_to_c_str(path); + dir.dir = opendir(c_str); + al_free(c_str); + if (!dir.dir) { + if (errno != ENOENT) { + al_log_error("file", "opendir(%.*s) failed (%s).", AL_STR_PRINTF(path), aki_strerror(errno)); + } + return false; + } + return true; +} + +bool aki_dir_create(str *path) +{ + char *c_str = al_str_to_c_str(path); + s32 ret = mkdir(c_str, 0700); + al_free(c_str); + if (ret == -1) { + al_log_error("file", "mkdir(%.*s) failed (%s).", AL_STR_PRINTF(path), aki_strerror(errno)); + return false; + } + return true; +} + +bool aki_dir_read(struct aki_dir *dir, struct aki_dir_entry *entry) +{ + errno = 0; + entry->entry = readdir(dir->dir); + if (!entry->entry) { + if (errno) { + al_log_error("file", "readdir() failed (%s).", aki_strerror(errno)); + } + return false; + } + switch (entry->entry->d_type) { + case DT_REG: + case DT_UNKNOWN: + entry->type = AKI_ENTRY_FILE; + break; + case DT_DIR: + entry->type = AKI_ENTRY_DIR; + break; + default: + entry->type = AKI_ENTRY_OTHER; + break; + } + al_str_clone(&entry->name, al_str_c(entry->entry->d_name)); + al_str_clone(&entry->path, &dir->path); + al_str_cat(&entry->path, al_str_c("/")); + al_str_cat(&entry->path, &entry->name); + return true; +} + +void aki_dir_entry_free(struct aki_dir_entry *entry) +{ + al_str_free(&entry->name); + al_str_free(&entry->path); +} diff --git a/src/util/file/file_stdio.c b/src/util/file/file_stdio.c new file mode 100644 index 0000000..52d8761 --- /dev/null +++ b/src/util/file/file_stdio.c @@ -0,0 +1,100 @@ +#include <al/log.h> + +#include "../error.h" + +#include "file.h" + +bool aki_file_open(struct aki_file *file, str *path, bool create) +{ + char *c_str = al_str_to_c_str(path); + const char *mode = create ? "wb+" : "rb+"; +#ifndef _WIN32 + file->file = fopen(c_str, mode); +#else + errno_t ret = fopen_s(&file->file, c_str, mode); +#endif + al_free(c_str); +#ifndef _WIN32 + if (!file->file) { +#else + if (ret != 0) { +#endif + al_log_error("file_stdio", "fopen(%.*s) failed (%s).", AL_STR_PRINTF(path), aki_strerror(errno)); + return false; + } + off_t pos = aki_file_seek(file, 0, SEEK_END); + if (pos == -1) { + aki_file_close(file); + return false; + } + file->filesize = pos; + rewind(file->file); + return true; +} + +bool aki_file_exists(str *path) +{ + (void)path; + return false; +} + +off_t aki_file_seek(struct aki_file *file, off_t offset, s32 whence) +{ + if (fseek(file->file, offset, whence) != 0) { + al_log_error("file_stdio", "fseek(%jd, %d) failed (%s).", (intmax_t)offset, + whence, aki_strerror(errno)); + return -1; + } + return ftell(file->file); +} + +bool aki_file_truncate(struct aki_file *file, off_t size) +{ + (void)file; + (void)size; + return true; +} + +size_t aki_file_get_filesize(struct aki_file *file) +{ + return file->filesize; +} + +bool aki_file_write(struct aki_file *file, void *buf, size_t size) +{ + size_t ret = fwrite(buf, size, 1, file->file); + if (ret == 0) { + al_log_error("file_stdio", "fwrite(%zu) failed (%s).", size, aki_strerror(errno)); + return false; + } + return true; +} + +bool aki_file_read(struct aki_file *file, void *buf, size_t size) +{ + size_t ret = fread(buf, size, 1, file->file); + if (ret == 0) { + al_log_error("file_stdio", "fread(%zu) failed (%s).", size, aki_strerror(errno)); + return false; + } + return true; +} + +void *aki_file_mmap(struct aki_file *file) +{ + (void)file; + al_assert(false); + return NULL; +} + +void aki_file_close(struct aki_file *file) +{ + fclose(file->file); +} + +bool aki_dir_open(struct aki_dir *dir, str *path) { (void)dir; (void)path; return false; } +void aki_dir_close(struct aki_dir *dir) { (void)dir; } +bool aki_dir_exists(str *path) { (void)path; return false; } +bool aki_dir_create(str *path) { (void)path; return false; } +bool aki_dir_read(struct aki_dir *dir, struct aki_dir_entry *entry) { (void)dir; (void)entry; return false; } +void aki_dir_entry_free(struct aki_dir_entry *entry) { (void)entry; } diff --git a/src/util/file/util.c b/src/util/file/util.c new file mode 100644 index 0000000..e893de7 --- /dev/null +++ b/src/util/file/util.c @@ -0,0 +1,25 @@ +#include "file.h" + +s32 aki_file_read_as_str(struct aki_file *file, str *out) +{ + size_t size = file->filesize; + al_str_sized(out, size); + if (!aki_file_read(file, (void *)out->data, size)) { + al_str_free(out); + return -1; + } + out->len = size; + return size; +} + +s32 aki_file_read_as_c_str(struct aki_file *file, char **out) +{ + size_t size = file->filesize; + *out = al_malloc(size + 1); + if (!aki_file_read(file, (void *)*out, size)) { + al_free(*out); + return -1; + } + (*out)[size] = '\n'; + return size; +} diff --git a/src/util/packet.c b/src/util/packet.c new file mode 100644 index 0000000..c58d656 --- /dev/null +++ b/src/util/packet.c @@ -0,0 +1,104 @@ +#include "packet.h" + +struct aki_packet *aki_packet_create(void) +{ + struct aki_packet *packet = (struct aki_packet *)al_malloc(sizeof(struct aki_packet)); + aki_buffer_init(&packet->buffer); + aki_packet_reset(packet); + return packet; +} + +struct aki_packet *aki_packet_clone(struct aki_packet *packet) +{ + struct aki_packet *c = aki_packet_create(); + aki_buffer_ensure_size(&c->buffer, packet->buffer.size); + al_memcpy(aki_buffer_get_ptr(&c->buffer, 0), aki_buffer_get_ptr(&packet->buffer, 0), packet->buffer.size); + c->windex = packet->windex; + c->rindex = packet->rindex; + return c; +} + +void aki_packet_reset(struct aki_packet *packet) +{ + aki_buffer_ensure_size(&packet->buffer, AKI_PACKET_HEADER_LENGTH); + packet->rindex = AKI_PACKET_HEADER_LENGTH; + packet->windex = AKI_PACKET_HEADER_LENGTH; +} + +void aki_packet_write_size(struct aki_packet *packet) +{ + *((u32 *)aki_buffer_get_ptr(&packet->buffer, 0)) = packet->windex; +} + +u32 aki_packet_size(struct aki_packet *packet) +{ + return *((u32 *)aki_buffer_get_ptr(&packet->buffer, 0)); +} + +#define DEFINE_PACKET_WRITE_FUNC(type) \ + void aki_packet_write_##type(struct aki_packet *packet, type v) \ + { \ + AKI_PACKET_WRITE_TYPE(packet, type, v); \ + } + +DEFINE_PACKET_WRITE_FUNC(u8) +DEFINE_PACKET_WRITE_FUNC(s8) +DEFINE_PACKET_WRITE_FUNC(u16) +DEFINE_PACKET_WRITE_FUNC(s16) +DEFINE_PACKET_WRITE_FUNC(u32) +DEFINE_PACKET_WRITE_FUNC(s32) +DEFINE_PACKET_WRITE_FUNC(u64) +DEFINE_PACKET_WRITE_FUNC(s64) +DEFINE_PACKET_WRITE_FUNC(f32) +DEFINE_PACKET_WRITE_FUNC(f64) + +void aki_packet_write_string(struct aki_packet *packet, str *s) +{ + AKI_PACKET_WRITE_TYPE(packet, u32, s->len); + AKI_PACKET_WRITE_DATA(packet, s->data, s->len); +} + +void aki_packet_write_buffer(struct aki_packet *packet, struct aki_buffer *buf) +{ + AKI_PACKET_WRITE_TYPE(packet, size_t, buf->size); + AKI_PACKET_WRITE_DATA(packet, aki_buffer_get_ptr(buf, 0), buf->size); +} + +#define DEFINE_PACKET_READ_FUNC(type) \ + type aki_packet_read_##type(struct aki_packet *packet) \ + { \ + type r; \ + AKI_PACKET_READ_TYPE(packet, type, r); \ + return r; \ + } + +DEFINE_PACKET_READ_FUNC(u8) +DEFINE_PACKET_READ_FUNC(s8) +DEFINE_PACKET_READ_FUNC(u16) +DEFINE_PACKET_READ_FUNC(s16) +DEFINE_PACKET_READ_FUNC(u32) +DEFINE_PACKET_READ_FUNC(s32) +DEFINE_PACKET_READ_FUNC(u64) +DEFINE_PACKET_READ_FUNC(s64) +DEFINE_PACKET_READ_FUNC(f32) +DEFINE_PACKET_READ_FUNC(f64) + +void aki_packet_read_string(struct aki_packet *packet, str *s) +{ + AKI_PACKET_READ_TYPE(packet, u32, s->len); + AKI_PACKET_READ_DATA(packet, s->len, s->data); + s->alloc = 0; +} + +void aki_packet_read_buffer(struct aki_packet *packet, struct aki_buffer *buf) +{ + AKI_PACKET_READ_TYPE(packet, size_t, buf->size); + AKI_PACKET_READ_DATA(packet, buf->size, buf->data); + buf->alloc = 0; +} + +void aki_packet_free(struct aki_packet *packet) +{ + aki_buffer_free(&packet->buffer); + al_free(packet); +} diff --git a/src/util/packet.h b/src/util/packet.h new file mode 100644 index 0000000..14acf68 --- /dev/null +++ b/src/util/packet.h @@ -0,0 +1,65 @@ +#pragma once + +#include <al/types.h> +#include <al/str.h> +#include <al/array.h> + +#include "../util/buffer.h" + +#define AKI_PACKET_HEADER_LENGTH (u32)(sizeof(u32)) + +struct aki_packet { + struct aki_buffer buffer; + u32 rindex; + u32 windex; + void *userdata; +}; + +#define AKI_PACKET_WRITE_TYPE(p, type, v) \ + aki_buffer_write(&(p)->buffer, &(v), (p)->windex, sizeof(type)); \ + (p)->windex += (u32)sizeof(type) + +#define AKI_PACKET_WRITE_DATA(p, data, len) \ + aki_buffer_write(&(p)->buffer, (data), (p)->windex, (len)); \ + (p)->windex += (u32)len + +#define AKI_PACKET_READ_TYPE(p, type, r) \ + r = *((type *)aki_buffer_get_ptr(&(p)->buffer, (p)->rindex)); \ + (p)->rindex += (u32)sizeof(type); + +#define AKI_PACKET_READ_DATA(p, len, r) \ + r = (void *)aki_buffer_get_ptr(&(p)->buffer, (p)->rindex); \ + (p)->rindex += (u32)len; + +struct aki_packet *aki_packet_create(void); +struct aki_packet *aki_packet_clone(struct aki_packet *packet); +void aki_packet_reset(struct aki_packet *packet); + +void aki_packet_write_size(struct aki_packet *packet); +u32 aki_packet_size(struct aki_packet *packet); + +void aki_packet_write_s8(struct aki_packet *packet, s8 v); +void aki_packet_write_u8(struct aki_packet *packet, u8 v); +void aki_packet_write_s16(struct aki_packet *packet, s16 v); +void aki_packet_write_u16(struct aki_packet *packet, u16 v); +void aki_packet_write_s32(struct aki_packet *packet, s32 v); +void aki_packet_write_u32(struct aki_packet *packet, u32 v); +void aki_packet_write_s64(struct aki_packet *packet, s64 v); +void aki_packet_write_u64(struct aki_packet *packet, u64 v); +void aki_packet_write_f32(struct aki_packet *packet, f32 v); +void aki_packet_write_string(struct aki_packet *packet, str *s); +void aki_packet_write_buffer(struct aki_packet *packet, struct aki_buffer *buf); + +s8 aki_packet_read_s8(struct aki_packet *packet); +u8 aki_packet_read_u8(struct aki_packet *packet); +s16 aki_packet_read_s16(struct aki_packet *packet); +u16 aki_packet_read_u16(struct aki_packet *packet); +s32 aki_packet_read_s32(struct aki_packet *packet); +u32 aki_packet_read_u32(struct aki_packet *packet); +s64 aki_packet_read_s64(struct aki_packet *packet); +u64 aki_packet_read_u64(struct aki_packet *packet); +f32 aki_packet_read_f32(struct aki_packet *packet); +void aki_packet_read_string(struct aki_packet *packet, str *s); +void aki_packet_read_buffer(struct aki_packet *packet, struct aki_buffer *buf); + +void aki_packet_free(struct aki_packet *packet); diff --git a/src/util/thread/thread.h b/src/util/thread/thread.h new file mode 100644 index 0000000..eb63b8d --- /dev/null +++ b/src/util/thread/thread.h @@ -0,0 +1,66 @@ +#pragma once + +#include <al/types.h> + +#ifndef _WIN32 +#include <pthread.h> +#else +#include "../../winwrap.h" +#endif + +struct aki_thread { +#ifndef _WIN32 + pthread_t thread; +#else + HANDLE thread; +#endif +}; + +struct aki_mutex { +#ifndef _WIN32 + pthread_mutex_t mutex; +#else + CRITICAL_SECTION mutex; +#endif +}; + +struct aki_cond { +#ifndef _WIN32 + pthread_cond_t cond; +#else + CONDITION_VARIABLE cond; +#endif + bool condition; +}; + +typedef f64 aki_os_tstamp; + +#define AKI_TS_FROM_USEC(usec) (usec * 1e-6) + +#ifndef _WIN32 +#define AKI_THREADCALL +typedef void * aki_thread_result; +#else +#define AKI_THREADCALL __stdcall +typedef unsigned long aki_thread_result; +#endif + +typedef aki_thread_result (AKI_THREADCALL * aki_thread_func)(void *); + +void aki_thread_sleep(aki_os_tstamp ts); + +void aki_thread_create(struct aki_thread *thread, aki_thread_func func, void *userdata); +void aki_thread_join(struct aki_thread *thread); +//void aki_thread_cancel(struct aki_thread *thread); +//void aki_thread_detach(struct aki_thread *thread); + +void aki_mutex_init(struct aki_mutex *mutex); +void aki_mutex_lock(struct aki_mutex *mutex); +void aki_mutex_unlock(struct aki_mutex *mutex); +void aki_mutex_destroy(struct aki_mutex *mutex); + +void aki_cond_init(struct aki_cond *cond); +void aki_cond_wait(struct aki_cond *cond, struct aki_mutex *mutex); +bool aki_cond_is_waiting(struct aki_cond *cond); +void aki_cond_signal(struct aki_cond *cond); +void aki_cond_destroy(struct aki_cond *cond); diff --git a/src/util/thread/thread_linux.c b/src/util/thread/thread_linux.c new file mode 100644 index 0000000..0214ed8 --- /dev/null +++ b/src/util/thread/thread_linux.c @@ -0,0 +1,86 @@ +#include <al/types.h> +#include <time.h> + +#include "../error.h" + +#include "thread.h" + +void aki_thread_sleep(aki_os_tstamp ts) +{ + struct timespec tv; + tv.tv_sec = (s64)ts; + tv.tv_nsec = (s64)((ts - tv.tv_sec) * 1e9); + while (nanosleep(&tv, &tv) == -1 && errno == EINTR) {} +} + +void aki_thread_create(struct aki_thread *thread, aki_thread_func func, void *userdata) +{ + pthread_create(&thread->thread, NULL, func, userdata); +} + +void aki_thread_join(struct aki_thread *thread) +{ + pthread_join(thread->thread, NULL); +} + +/* +void aki_thread_cancel(struct aki_thread *thread) +{ + pthread_cancel(thread->thread); +} + +void aki_thread_detach(struct aki_thread *thread) +{ + pthread_detach(thread->thread); +} +*/ + +void aki_mutex_init(struct aki_mutex *mutex) +{ + pthread_mutex_init(&mutex->mutex, NULL); +} + +void aki_mutex_lock(struct aki_mutex *mutex) +{ + pthread_mutex_lock(&mutex->mutex); +} + +void aki_mutex_unlock(struct aki_mutex *mutex) +{ + pthread_mutex_unlock(&mutex->mutex); +} + +void aki_mutex_destroy(struct aki_mutex *mutex) +{ + pthread_mutex_destroy(&mutex->mutex); +} + +void aki_cond_init(struct aki_cond *cond) +{ + cond->condition = true; + pthread_cond_init(&cond->cond, NULL); +} + +void aki_cond_wait(struct aki_cond *cond, struct aki_mutex *mutex) +{ + cond->condition = false; + while (!cond->condition) { + pthread_cond_wait(&cond->cond, &mutex->mutex); + } +} + +bool aki_cond_is_waiting(struct aki_cond *cond) +{ + return !cond->condition; +} + +void aki_cond_signal(struct aki_cond *cond) +{ + cond->condition = true; + pthread_cond_signal(&cond->cond); +} + +void aki_cond_destroy(struct aki_cond *cond) +{ + pthread_cond_destroy(&cond->cond); +} diff --git a/src/util/thread/thread_windows.c b/src/util/thread/thread_windows.c new file mode 100644 index 0000000..9ea9ead --- /dev/null +++ b/src/util/thread/thread_windows.c @@ -0,0 +1,81 @@ +#include "thread.h" + +NTSTATUS(__stdcall *NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval); + +void aki_thread_sleep(aki_os_tstamp ts) +{ + LARGE_INTEGER intr; + intr.QuadPart = -1 * (s64)(ts * 1e7); + NtDelayExecution(false, &intr); +} + +void aki_thread_create(struct aki_thread *thread, aki_thread_func func, void *userdata) +{ + thread->thread = CreateThread(NULL, 0, func, userdata, 0, NULL); +} + +void aki_thread_join(struct aki_thread *thread) +{ + WaitForSingleObject(thread->thread, INFINITE); + CloseHandle(thread->thread); +} + +/* +void aki_thread_cancel(struct aki_thread *thread) +{ +} + +void aki_thread_detach(struct aki_thread *thread) +{ +} +*/ + +void aki_mutex_init(struct aki_mutex *mutex) +{ + InitializeCriticalSection(&mutex->mutex); +} + +void aki_mutex_lock(struct aki_mutex *mutex) +{ + EnterCriticalSection(&mutex->mutex); +} + +void aki_mutex_unlock(struct aki_mutex *mutex) +{ + LeaveCriticalSection(&mutex->mutex); +} + +void aki_mutex_destroy(struct aki_mutex *mutex) +{ + DeleteCriticalSection(&mutex->mutex); +} + +void aki_cond_init(struct aki_cond *cond) +{ + cond->condition = true; + InitializeConditionVariable(&cond->cond); +} + +void aki_cond_wait(struct aki_cond *cond, struct aki_mutex *mutex) +{ + cond->condition = false; + while (!cond->condition) { + SleepConditionVariableCS(&cond->cond, &mutex->mutex, INFINITE); + } +} + +bool aki_cond_is_waiting(struct aki_cond *cond) +{ + return !cond->condition; +} + +void aki_cond_signal(struct aki_cond *cond) +{ + cond->condition = true; + WakeConditionVariable(&cond->cond); +} + +void aki_cond_destroy(struct aki_cond *cond) +{ + (void)cond; +} diff --git a/src/util/timer/timer.h b/src/util/timer/timer.h new file mode 100644 index 0000000..2bf6b95 --- /dev/null +++ b/src/util/timer/timer.h @@ -0,0 +1,6 @@ +#pragma once + +#include <al/types.h> + +u64 aki_get_timestamp(void); +f64 aki_get_tick(void); diff --git a/src/util/timer/timer_linux.c b/src/util/timer/timer_linux.c new file mode 100644 index 0000000..d93bfdc --- /dev/null +++ b/src/util/timer/timer_linux.c @@ -0,0 +1,17 @@ +#include <time.h> + +#include "timer.h" + +u64 aki_get_timestamp(void) +{ + struct timespec spec; + clock_gettime(CLOCK_REALTIME, &spec); + return 1e6 * spec.tv_sec + spec.tv_nsec * 1e-3; +} + +f64 aki_get_tick(void) +{ + struct timespec spec; + clock_gettime(CLOCK_MONOTONIC, &spec); + return spec.tv_sec + spec.tv_nsec * 1e-9; +} diff --git a/src/util/timer/timer_windows.c b/src/util/timer/timer_windows.c new file mode 100644 index 0000000..37a8fd8 --- /dev/null +++ b/src/util/timer/timer_windows.c @@ -0,0 +1,39 @@ +#include <al/lib.h> + +#include "../../winwrap.h" + +#include "timer.h" + +f64 aki_get_tick(void) +{ + LARGE_INTEGER result; + QueryPerformanceCounter(&result); + return (result.QuadPart/(f64)performance_frequency.QuadPart); +} + +static SYSTEMTIME unix_epoch = { + .wYear = 1970, + .wMonth = 1, + .wDayOfWeek = 4, + .wDay = 1, + .wHour = 0, + .wMinute = 0, + .wSecond = 0, + .wMilliseconds = 0 +}; + +u64 aki_get_timestamp(void) +{ + FILETIME result0, result1; + SystemTimeToFileTime(&unix_epoch, &result0); + ULARGE_INTEGER li0 = { + .LowPart = result0.dwLowDateTime, + .HighPart = result0.dwHighDateTime + }; + GetSystemTimePreciseAsFileTime(&result1); + ULARGE_INTEGER li1 = { + .LowPart = result1.dwLowDateTime, + .HighPart = result1.dwHighDateTime + }; + return (li1.QuadPart - li0.QuadPart) / 10; +} |