clay/src/clay-context.c

126 lines
3.8 KiB
C

#include <clay.h>
#include <stddef.h>
#include <malloc.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include "clay-layout.h"
#include "clay-context.h"
// todo: thread safety? maybe as an option CLAY_ENABLE_THREADSAFE
struct clay_ctx_t {
clay *layouts_ptrs;
size_t layouts_length;
size_t layouts_size;
clay_property_desc_s *property_descs;
size_t property_descs_length;
size_t property_descs_size;
int property_tag_cnt;
};
clay_ctx clay_create_context(void) {
clay_ctx ctx = malloc(sizeof *ctx);
assert(ctx != NULL);
ctx->layouts_size = 16;
ctx->layouts_length = 0;
ctx->layouts_ptrs = malloc(sizeof(*ctx->layouts_ptrs) * ctx->layouts_size);
assert(ctx->layouts_ptrs != NULL);
ctx->property_tag_cnt = 0;
ctx->property_descs_size = 16;
ctx->property_descs_length = 0;
ctx->property_descs = malloc(sizeof(*ctx->property_descs) * ctx->property_descs_size);
assert(ctx->property_descs != NULL);
clay_text_register_props(ctx);
clay_flex_register_props(ctx);
clay_document_register_props(ctx);
return ctx;
}
void clay_destroy_context(clay_ctx ctx) {
// TODO: free everything owned by ctx
for (size_t i = 0; i < ctx->layouts_length; ++i) {
clay layout = ctx->layouts_ptrs[i];
clay_cleanup_layout(layout);
free(layout);
}
free(ctx->layouts_ptrs);
free(ctx->property_descs);
free(ctx);
}
void clay_ctx_register_layout(clay_ctx ctx, clay layout) {
assert(ctx->layouts_length <= ctx->layouts_size);
if (ctx->layouts_length == ctx->layouts_size) {
size_t new_size = ctx->layouts_size * 2;
ctx->layouts_ptrs = realloc(ctx->layouts_ptrs, sizeof(*ctx->layouts_ptrs) * new_size);
assert(ctx->layouts_ptrs != NULL);
ctx->layouts_size = new_size;
}
ctx->layouts_length += 1;
ctx->layouts_ptrs[ctx->layouts_length - 1] = layout;
}
void clay_ctx_unregister_layout(clay_ctx ctx, clay layout) {
for (size_t i = 0; i < ctx->layouts_length; ++i) {
if (ctx->layouts_ptrs[i] == layout) {
ctx->layouts_ptrs[i] = ctx->layouts_ptrs[ctx->layouts_length - 1];
ctx->layouts_length -= 1;
}
}
}
int clay_ctx_register_property(clay_ctx ctx, const char *name, clay_property_type type) {
assert (!clay_ctx_has_property(ctx, name));
int tag = ++ctx->property_tag_cnt;
assert(ctx->property_descs_length <= ctx->property_descs_size);
if (ctx->property_descs_length == ctx->property_descs_size) {
size_t new_size = ctx->property_descs_size * 2;
ctx->property_descs = realloc(ctx->property_descs, sizeof(*ctx->property_descs) * new_size);
assert(ctx->property_descs != NULL);
ctx->property_descs_size = new_size;
}
ctx->property_descs_length += 1;
ctx->property_descs[ctx->property_descs_length - 1] = (clay_property_desc_s) {
.type = type,
.tag = tag,
.name = name
};
return tag;
}
void clay_ctx_unregister_property(clay_ctx ctx, int tag) {
for (size_t i = 0; i < ctx->property_descs_length; ++i) {
if (ctx->property_descs[i].tag == tag) {
ctx->property_descs[i] = ctx->property_descs[ctx->property_descs_length - 1];
ctx->property_descs_length -= 1;
return;
}
}
}
bool clay_ctx_has_property(clay_ctx ctx, const char *name) {
for (size_t i = 0; i < ctx->property_descs_length; ++i) {
if (strcmp(ctx->property_descs[i].name, name) == 0) {
return true;
}
}
return false;
}
clay_property_desc clay_ctx_get_property_desc(clay_ctx ctx, const char *name) {
for (size_t i = 0; i < ctx->property_descs_length; ++i) {
if (strcmp(ctx->property_descs[i].name, name) == 0) {
return &ctx->property_descs[i];
}
}
return NULL;
}