/* ** C Scripting - Hooks */ #define SY__MAIN 1 #include "symbol_set.h" #include "symbol_set.init.h" #include "hooks.h" #include #include #include //////////////////////////////// // 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), ¶ms); } ctx_hook_all_processes(&ctx, SyID(HOOK_POINT, EndFrame), 0); } return(0); }