global character_registry *Global_CharacterRegistry = 0; //////////////////////////////// //~ sixten: Character String Chunk Functions static character_string_list CR_CharacterStringListAlloc(character_registry *Registry, string String) { character_string_list Result = {}; s64 ChunksNeeded = (String.Count + CHARACTER_STRING_CHUNK_DATA_SIZE - 1) / CHARACTER_STRING_CHUNK_DATA_SIZE; s64 BytesLeft = String.Count; u64 StringIndex = 0; for(s64 ChunkIndex = 0; ChunkIndex < ChunksNeeded; ChunkIndex += 1) { character_string_chunk *Chunk = Registry->FirstFreeChunk; if(Chunk) { Registry->FirstFreeChunk = Chunk->Next; } else { Chunk = PushStructNoClear(Registry->StringArena, character_string_chunk); } u64 ToCopy = Min(BytesLeft, CHARACTER_STRING_CHUNK_DATA_SIZE); Copy(Chunk->Data, String.Data+StringIndex, ToCopy); QueuePush(Result.First, Result.Last, Chunk); Result.ChunkCount += 1; Result.StringCount += ToCopy; BytesLeft -= ToCopy; StringIndex += ToCopy; } return(Result); } static character_string_list CR_CharacterStringListRelease(character_registry *Registry, character_string_list *List) { for(character_string_chunk *Chunk = List->First, *Next = 0; Chunk != 0; Chunk = Next) { Next = Chunk->Next; Chunk->Next = Registry->FirstFreeChunk; Registry->FirstFreeChunk = Chunk; } ZeroStruct(List); } static string CR_StringFromList(memory_arena *Arena, character_string_list *List) { string Result; Result.Count = List->StringCount; Result.Data = PushArrayNoClear(Arena, u8, Result.Count); s64 StringIndex = 0; s64 BytesLeft = List->StringCount; for(character_string_chunk *Chunk = List->First; Chunk != 0; Chunk = Chunk->Next) { s64 ToCopy = Min(BytesLeft, CHARACTER_STRING_CHUNK_DATA_SIZE); Copy(Result.Data+StringIndex, Chunk->Data, ToCopy); StringIndex += ToCopy; BytesLeft -= ToCopy; } return(Result); } //////////////////////////////// //~ sixten: Character Registry Functions static void CR_SetState(character_registry *State) { Global_CharacterRegistry = State; } static character_registry *CR_GetState(void) { return(Global_CharacterRegistry); } static character_list CR_GetCharacters(void) { return(CR_GetState()->Characters); } static void CR_Init(character_registry *State) { CR_SetState(State); State->Arena = ArenaAllocate(Megabytes(32)); } static character_entry *CR_EntryFromName(string Name) { character_entry *Entry = 0; character_registry *Registry = CR_GetState(); for(character_entry *Iter = Registry->Characters.First; Iter != 0; Iter = Iter->Next) { if(AreEqual(Name, Iter->Name)) { Entry = Iter; break; } } if(!Entry) { Entry = PushStruct(Registry->Arena, character_entry); Entry->Name = PushString(Registry->Arena, Name); DLLInsertLast(Registry->Characters.First, Registry->Characters.Last, Entry); } return(Entry); }