//////////////////////////////////////////////////////////// //~ Bootstrap void BootstrapTweakVars(void) { // TODO: Swap in/out for persistence } //////////////////////////////////////////////////////////// //~ Tweak var operations String TweakEx(Arena *arena, TweakVar desc, b32 update_existing) { String result = Zi; Arena *perm = PermArena(); u64 hash = HashString(desc.name); TweakVarEntryBin *bin = &Base.tweak.entry_bins[hash % countof(Base.tweak.entry_bins)]; LockTicketMutex(&Base.tweak.tm); { TweakVarEntry *e = bin->first; for (; e; e = e->next_in_bin) { if (e->hash == hash) { break; } } if (!e) { PushAlign(perm, CachelineSize); e = PushStruct(perm, TweakVarEntry); e->hash = hash; { // FIXME: Not perm String store_name = PushString(perm, desc.name); String store_category = PushString(perm, desc.category); String store_value = PushString(perm, desc.value); String store_initial = PushString(perm, desc.initial); TweakVar *v = &e->v; *v = desc; v->name = store_name; v->category = store_category; v->value = store_value; v->initial = store_initial; } PushAlign(perm, CachelineSize); SllQueuePushN(bin->first, bin->last, e, next_in_bin); SllQueuePushN(Base.tweak.first_entry, Base.tweak.last_entry, e, next_in_list); Base.tweak.entries_count += 1; } else if (update_existing) { if (!MatchString(e->v.value, desc.value)) { // FIXME: Not perm String store_value = PushString(perm, desc.value); // FIXME: free old value e->v.value = store_value; } } result = PushString(arena, e->v.value); } UnlockTicketMutex(&Base.tweak.tm); return result; } TweakVarArray GetAllTweakVars(Arena *arena) { TweakVarArray result = Zi; LockTicketMutex(&Base.tweak.tm); { result.count = Base.tweak.entries_count; result.v = PushStructsNoZero(arena, TweakVar, result.count); i64 var_idx = 0; for (TweakVarEntry *e = Base.tweak.first_entry; e; e = e->next_in_list) { TweakVar *src = &e->v; TweakVar *dst = &result.v[var_idx]; *dst = *src; dst->name = PushString(arena, src->name); dst->category = PushString(arena, src->category); dst->value = PushString(arena, src->value); dst->initial = PushString(arena, src->initial); var_idx += 1; } } UnlockTicketMutex(&Base.tweak.tm); return result; } //////////////////////////////////////////////////////////// //~ Tweak utils b32 TweakBool_(String name, b32 initial, TweakBoolDesc desc) { b32 result = 0; TempArena scratch = BeginScratchNoConflict(); { String initial_str = StringFromBool(scratch.arena, initial); TweakVar var = Zi; { var.flags = desc.flags; var.kind = TweakKind_Bool; var.name = name; var.category = desc.category; var.value = initial_str; var.initial = initial_str; } String tweak_str = TweakEx(scratch.arena, var, 0); result = CR_BoolFromString(tweak_str); } EndScratch(scratch); return result; } f64 TweakFloat_(String name, f64 initial, TweakFloatDesc desc) { f64 result = 0; TempArena scratch = BeginScratchNoConflict(); { String initial_str = StringFromFloat(scratch.arena, initial, desc.precision); TweakVar var = Zi; { var.flags = desc.flags; var.kind = TweakKind_Float; var.name = name; var.category = desc.category; var.value = initial_str; var.initial = initial_str; var.range.min = desc.min; var.range.max = desc.max; var.precision = desc.precision; } String tweak_str = TweakEx(scratch.arena, var, 0); result = CR_FloatFromString(tweak_str); } EndScratch(scratch); return result; }