160 lines
4.7 KiB
C
160 lines
4.7 KiB
C
#include "config.h"
|
|
|
|
sat_config_ptr sat_config_stream_scope_to(sat_config_ptr ctx, char *prefix) {
|
|
int pfxLength = strlen(prefix);
|
|
bool appendColon = prefix[pfxLength - 1] != ':';
|
|
|
|
int length = pfxLength + 1;
|
|
if(appendColon) length += 1;
|
|
|
|
char *newPrefix = malloc(length);
|
|
memset(newPrefix, 0, length);
|
|
strcat(newPrefix, prefix);
|
|
if(appendColon) strcat(newPrefix, ":");
|
|
|
|
sat_config_ptr scoped = sat_config_alloc_scoped();
|
|
sat_config_scoped_ptr scopedInfo = (sat_config_scoped_ptr)scoped->info;
|
|
scopedInfo->parent = ctx;
|
|
scopedInfo->prefix = newPrefix;
|
|
|
|
return scoped;
|
|
}
|
|
|
|
char* sat_config_stream_read_value(sat_config_ptr ctx, char *name, char *fallback) {
|
|
sat_config_stream_ptr info = (sat_config_stream_ptr)ctx->info;
|
|
|
|
// this buffer is reasonable, you are not
|
|
char buffer[1024] = {0};
|
|
char *value = NULL;
|
|
|
|
// this buffer is also reasonable, you still aren't
|
|
// given this name is only used in strcmp and the index of the ending would be known
|
|
// there's honestly very little reason to not just replace the first trailing space
|
|
// with a \0 character and just passing buffer to strcmp
|
|
char cName[256] = {0};
|
|
int cNameLength;
|
|
|
|
// should retry for like 10 seconds
|
|
mtx_lock(info->lock);
|
|
|
|
fseek(info->stream, info->offset, SEEK_SET);
|
|
|
|
// probably do trimming later
|
|
while(fgets(buffer, sizeof buffer, info->stream) != NULL) {
|
|
if(buffer[0] == '\0' || buffer[0] == '\r' || buffer[0] == '\n'
|
|
|| buffer[0] == ' ' || buffer[0] == '#' || buffer[0] == ';')
|
|
continue;
|
|
|
|
// skip ridiculous lines too
|
|
if(buffer[(sizeof buffer) - 1] != '\0') {
|
|
memset(buffer, 0, sizeof buffer);
|
|
continue;
|
|
}
|
|
|
|
cNameLength = 0;
|
|
while(buffer[cNameLength] != ' ' && buffer[cNameLength] != '\0')
|
|
++cNameLength;
|
|
|
|
cName[cNameLength] = '\0';
|
|
memcpy(cName, buffer, cNameLength);
|
|
|
|
if(strcmp(cName, name) == 0) {
|
|
int valueStart = cNameLength;
|
|
while(buffer[valueStart] == ' ')
|
|
++valueStart;
|
|
|
|
int valueEnd = valueStart;
|
|
while(buffer[valueEnd] != '\0' && buffer[valueEnd] != '\r' && buffer[valueEnd] != '\n')
|
|
++valueEnd;
|
|
|
|
int valueLength = valueEnd - valueStart;
|
|
if(valueLength > 0) {
|
|
value = malloc(valueLength + 1);
|
|
value[valueLength] = '\0';
|
|
memcpy(value, &buffer[valueStart], valueLength);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
mtx_unlock(info->lock);
|
|
|
|
if(value == NULL && fallback != NULL) {
|
|
int length = strlen(fallback) + 1;
|
|
value = malloc(length);
|
|
memset(value, 0, length);
|
|
strcat(value, fallback);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
sat_config_ptr sat_config_alloc_stream(void) {
|
|
sat_config_ptr ctx = malloc(sizeof(sat_config));
|
|
memset(ctx, 0, sizeof(sat_config));
|
|
ctx->type = SAT_CONFIG_TYPE_STREAM;
|
|
ctx->scopeTo = sat_config_stream_scope_to;
|
|
ctx->readValue = sat_config_stream_read_value;
|
|
|
|
sat_config_stream_ptr info = malloc(sizeof(sat_config_stream));
|
|
memset(info, 0, sizeof(sat_config_stream));
|
|
ctx->info = (void*)info;
|
|
info->lock = malloc(sizeof(mtx_t));
|
|
|
|
return ctx;
|
|
}
|
|
|
|
void sat_config_free_stream(sat_config_ptr ctx) {
|
|
if(ctx == NULL || ctx->info == NULL || ctx->type != SAT_CONFIG_TYPE_STREAM) return;
|
|
|
|
sat_config_stream_ptr info = (sat_config_stream_ptr)ctx->info;
|
|
|
|
if(info->lock != NULL) {
|
|
mtx_destroy(info->lock);
|
|
free(info->lock);
|
|
}
|
|
|
|
if(info->ownsStream && info->stream != NULL)
|
|
free(info->stream);
|
|
|
|
free(ctx->info);
|
|
free(ctx);
|
|
}
|
|
|
|
int sat_config_stream_open(sat_config_ptr ctx, FILE *stream, bool ownsStream) {
|
|
if(ctx == NULL) return -10; // TODO: No.
|
|
if(ctx->type != SAT_CONFIG_TYPE_STREAM) return -11;
|
|
if(ctx->info == NULL) return -12;
|
|
|
|
sat_config_stream_ptr info = (sat_config_stream_ptr)ctx->info;
|
|
|
|
int err = mtx_init(info->lock, mtx_timed);
|
|
if(err == thrd_error) return -11;
|
|
|
|
info->stream = stream;
|
|
info->ownsStream = ownsStream;
|
|
|
|
// check for BOM
|
|
uint8_t buffer[3] = {0};
|
|
int read = fread(buffer, sizeof(uint8_t), sizeof buffer, stream);
|
|
if(buffer[0] != 0xEF || buffer[1] != 0xBB || buffer[2] != 0xBF)
|
|
fseek(stream, -read, SEEK_CUR);
|
|
|
|
info->offset = ftell(stream);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sat_config_stream_open_file(sat_config_ptr ctx, char *path) {
|
|
if(ctx == NULL) return -10; // TODO: No!
|
|
if(ctx->type != SAT_CONFIG_TYPE_STREAM) return -11;
|
|
if(ctx->info == NULL) return -12;
|
|
|
|
FILE *stream = fopen(path, "rb");
|
|
if(stream == NULL) return errno;
|
|
|
|
fseek(stream, 0, SEEK_SET);
|
|
|
|
return sat_config_stream_open(ctx, stream, true);
|
|
}
|