temporary-satori-hole/src/persist.c
2023-12-27 01:35:22 +01:00

148 lines
5.2 KiB
C

#include "persist.h"
#define SAT_PERSIST_MAGIC (0xDEAFB00B)
#define SAT_PERSIST_VERSION (0x01)
#define SAT_PERSIST_HEADER (0x10)
#define SAT_PERSIST_FII_FORUM_LAST_POST_ID (0x10)
#define SAT_PERSIST_FII_USER_LAST_REGISTER_ID (0x18)
// that version number is going to come in useful cuz i want to expand the Persist.dat format
// v2 should add the ability to define a field by name
// i'm avoiding using the word "table" because in my eyes that implies a single block of data
// rather the table should be a linked list with the first entry pointed at from the header
// this way the existing fields in the v1 format don't have to be moved elsewhere during conversion
// essentially we got [DEAFB00B 02000000 20000000 00000000] in the header,
// the pointer to the first entry is at offset 0x08 in the header and should be interpreted as a U32
// why not a U64? cuz if we're gonna need more than the size a 32-bit integer offers we have worse problems than offset overflows...
// each entry will have a variable size, starting with a null terminated ascii string, followed by a byte for the type,
// followed by a U32 pointing to the location of the data, followed by a final U32 pointing to the next entry
// !!! this would remove the "backwards compatibility" of not having to move the data, but wouldn't it make more sense to
// !!! [NAME TYPE PNEXT VALUE] rather than [NAME TYPE PNEXT PVALUE]?
// i do not know how i'd go about values of variable length, perhaps the function that allocates a space in the file can review
// empty space or some kind of index can be kept, perhaps just add an asterisk saying "do not variable length you will regret"
// perhaps leave variable length shit for a v3 format
sat_persist_ptr sat_persist_alloc(void) {
sat_persist_ptr ctx = malloc(sizeof(sat_persist));
memset(ctx, 0, sizeof(sat_persist));
ctx->lock = malloc(sizeof(mtx_t));
return ctx;
}
void sat_persist_free(sat_persist_ptr ctx) {
if(!ctx) return;
if(ctx->lock != NULL) {
mtx_destroy(ctx->lock);
free(ctx->lock);
}
if(ctx->ownsStream && ctx->stream)
free(ctx->stream);
free(ctx);
}
int sat_persist_create(sat_persist_ptr ctx, FILE *stream, bool ownsStream) {
if(ctx == NULL) return -10; // TODO: No.
int err;
err = mtx_init(ctx->lock, mtx_timed);
if(err == thrd_error) return -11;
ctx->stream = stream;
ctx->ownsStream = ownsStream;
ctx->offset = ftell(stream);
err = sat_persist_header_refresh(ctx);
if(err) return err;
return 0;
}
int sat_persist_create_file(sat_persist_ptr ctx, char *path) {
if(ctx == NULL) return -10; // TODO: No!
FILE *stream = fopen(path, "rb+");
if(stream == NULL) stream = fopen(path, "wb+");
if(stream == NULL) return errno;
fseek(stream, 0, SEEK_SET);
return sat_persist_create(ctx, stream, true);
}
void sat_persist_flush(sat_persist_ptr ctx) {
if(ctx != NULL && ctx->stream != NULL)
fflush(ctx->stream);
}
int sat_persist_header_refresh(sat_persist_ptr ctx) {
uint8_t buffer[SAT_PERSIST_HEADER] = {0};
uint32_t magic;
mtx_lock(ctx->lock);
size_t read = fread(buffer, sizeof(uint8_t), SAT_PERSIST_HEADER, ctx->stream);
mtx_unlock(ctx->lock);
if(read == 0) {
sat_pack_u32be(buffer, SAT_PERSIST_MAGIC);
buffer[4] = SAT_PERSIST_VERSION;
mtx_lock(ctx->lock);
fseek(ctx->stream, ctx->offset, SEEK_SET);
fwrite(buffer, sizeof(uint8_t), SAT_PERSIST_HEADER, ctx->stream);
fflush(ctx->stream);
mtx_unlock(ctx->lock);
} else if(read < SAT_PERSIST_HEADER) {
return -2; // TODO: also no
} else {
magic = sat_unpack_u32be(buffer);
if(magic != SAT_PERSIST_MAGIC)
return -3; // TODO: still no
if(buffer[4] < 1 || buffer[4] > SAT_PERSIST_VERSION)
return -4; // TODO: again, no
}
return 0;
}
inline uint64_t sat_persist_read_u64(sat_persist_ptr ctx, uint32_t offset) {
uint8_t buffer[sizeof(uint64_t)] = {0};
mtx_lock(ctx->lock);
fseek(ctx->stream, ctx->offset + offset, SEEK_SET);
int read = fread(buffer, sizeof(uint8_t), sizeof(uint64_t), ctx->stream); // today we assume things will just work
mtx_unlock(ctx->lock);
if(read < 1) return 0;
return sat_unpack_u64le(buffer);
}
inline void sat_persist_write_u64(sat_persist_ptr ctx, uint32_t offset, uint64_t value) {
uint8_t buffer[sizeof(uint64_t)] = {0};
sat_pack_u64le(buffer, value);
mtx_lock(ctx->lock);
fseek(ctx->stream, ctx->offset + offset, SEEK_SET);
fwrite(buffer, sizeof(uint8_t), sizeof(uint64_t), ctx->stream);
mtx_unlock(ctx->lock);
}
uint64_t sat_persist_get_fii_forum_last_post_id(sat_persist_ptr ctx) {
return sat_persist_read_u64(ctx, SAT_PERSIST_FII_FORUM_LAST_POST_ID);
}
void sat_persist_set_fii_forum_last_post_id(sat_persist_ptr ctx, uint64_t postId) {
sat_persist_write_u64(ctx, SAT_PERSIST_FII_FORUM_LAST_POST_ID, postId);
}
uint64_t sat_persist_get_fii_user_last_register_id(sat_persist_ptr ctx) {
return sat_persist_read_u64(ctx, SAT_PERSIST_FII_USER_LAST_REGISTER_ID);
}
void sat_persist_set_fii_user_last_register_id(sat_persist_ptr ctx, uint64_t userId) {
sat_persist_write_u64(ctx, SAT_PERSIST_FII_USER_LAST_REGISTER_ID, userId);
}