c-scripting/examples/hooks.c

215 lines
5.1 KiB
C

/*
** C Scripting - Hooks
*/
#define SY__MAIN 1
#include "symbol_set.h"
#include "symbol_set.init.h"
#include "hooks.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
////////////////////////////////
// Little Base Layer
static Arena
arena_alloc(U64 cap){
Arena arena = {0};
arena.memory = malloc(cap);
arena.cap = cap;
return(arena);
}
static void*
arena_push(Arena *arena, U64 size){
void *result = 0;
if (arena->pos + size <= arena->cap){
result = (U8*)arena->memory + arena->pos;
arena->pos += size;
arena->pos = (arena->pos + 7)&~7; // "round up to multiple of 8"
memset(result, 0, size);
}
return(result);
}
static void
arena_pop_to(Arena *arena, U64 pos){
if (pos < arena->pos){
arena->pos = (pos + 7)&~7; // "round up to multiple of 8"
}
}
static U64
arena_pos(Arena *arena){
return(arena->pos);
}
static void*
copy_strided(void *dst, U32 dst_stride,
void *src, U32 src_stride,
U32 count){
void *base_src = src;
void *base_dst = dst;
if (dst_stride != src_stride){
U32 size = Min(dst_stride, src_stride);
for (U32 i = 0; i < count; i += 1){
memcpy(dst, src, size);
dst = (U8*)dst + dst_stride;
src = (U8*)src + src_stride;
}
}
else{
memcpy(dst, src, dst_stride*count);
}
return(base_dst);
}
static void*
arena_push_symbol_set__raw(Arena *arena,
U32 size, void *src, U32 src_stride, U32 count){
void *dst = push_array(arena, U8, size*(count + 1));
copy_strided((U8*)dst + size, size, src, src_stride, count);
return(dst);
}
////////////////////////////////
// Pretend "Core API"
typedef struct BufferRenderCtx{
U32 dummy;
} BufferRenderCtx;
static void
color_range(Ctx *ctx, U32 min, U32 max){
printf("DEMO: color_word(%p, %u, %u)\n", ctx, min, max);
}
////////////////////////////////
// Hooks
//// Symbols ////
HOOK_POINT_TYPE_DEF(BeginFrame, void);
HOOK_POINT_TYPE_DEF(EndFrame, void);
HOOK_POINT_STRUCT(RenderBuffer){
U32 buffer_id;
};
PROCESS_TYPE(SearchWord);
PROCESS_HOOK(SearchWord, RenderBuffer){
// imagine you get the string from the process
String8 string = str8_const("c-scripting");
// imagine you get the match ranges from searching params->buffer_id
U32 range_count = 0;
U32 rmin[3] = {0};
if (params->buffer_id == 1){
range_count = 3;
memcpy(rmin, (U32[3]){ 1, 20, 152 }, 12);
}
else if (params->buffer_id == 2){
range_count = 2;
memcpy(rmin, (U32[2]){ 72, 510 }, 8);
}
// color the ranges
for (U32 i = 0; i < range_count; i += 1){
color_range(ctx, rmin[i], rmin[i] + string.size);
}
}
//// Rules ////
static Rules
rules_from_symbol_sets(Arena *arena){
// copy named symbol sets
U32 hook_point_count = SyCount(HOOK_POINT) + 1;
HookPoint *hook_points = arena_push_symbol_set(arena, HOOK_POINT);
U32 process_type_count = SyCount(PROCESS_TYPE) + 1;
ProcessType *process_types = arena_push_symbol_set(arena, PROCESS_TYPE);
// process unnamed symbol sets
HookFunc **func__process_hook =
push_array(arena, HookFunc*, hook_point_count*process_type_count);
for (SyEach(PROCESS_HOOK, link)){
U32 idx = link->process_type_id*hook_point_count + link->hook_point_id;
func__process_hook[idx] = link->func;
}
// rules
Rules rules = {
.hook_point_count = hook_point_count,
.process_type_count = process_type_count,
.hook_points = hook_points,
.process_types = process_types,
.func__process_hook = func__process_hook
};
return(rules);
}
static HookFunc*
rules_func_from_process_hook(Rules *rules, U32 process_type_id, U32 hook_point_id){
U32 idx = process_type_id*rules->hook_point_count + hook_point_id;
HookFunc *result = rules->func__process_hook[idx];
return(result);
}
//// Context Functions ////
static void
ctx_new_process(Ctx *ctx, U32 process_type_id){
if (ctx->process_count < sizeof(ctx->process_type_id)/sizeof(*ctx->process_type_id)){
ctx->process_type_id[ctx->process_count] = process_type_id;
ctx->process_count += 1;
}
}
static void
ctx_hook_all_processes(Ctx *ctx, U32 hookp_id, void *params){
for (U32 i = 0; i < ctx->process_count; i += 1){
U32 process_type_id = ctx->process_type_id[i];
HookFunc *func = rules_func_from_process_hook(ctx->rules, process_type_id, hookp_id);
if (func != 0){
func(ctx, params);
}
}
}
//// Entry Point ////
int main(void){
sy__run_init();
Arena arena = arena_alloc((10 << 20));
Rules rules = rules_from_symbol_sets(&arena);
Ctx ctx = {0};
ctx.rules = &rules;
ctx_new_process(&ctx, SyID(PROCESS_TYPE, SearchWord));
for (U32 i = 0; i < 100; i += 1){
ctx_hook_all_processes(&ctx, SyID(HOOK_POINT, BeginFrame), 0);
for (U32 viewi = 0; viewi < 2; viewi += 1){
// imagine each view has an assigned buffer
U32 buffer_id = viewi + 1;
// render the buffer
HOOK_POINT_TYPE(RenderBuffer) params = {
params.buffer_id = buffer_id
};
ctx_hook_all_processes(&ctx, SyID(HOOK_POINT, RenderBuffer), &params);
}
ctx_hook_all_processes(&ctx, SyID(HOOK_POINT, EndFrame), 0);
}
return(0);
}