Lumenarium/meta/gs_string_builder.h

99 lines
2.7 KiB
C
Raw Normal View History

#define STRING_BUILDER_ARRAY_BUFFER_SIZE 32
struct string_array
{
string** Buckets;
s32 BucketSize;
s32 BucketCount;
s32 Used;
free_list FreeList;
};
internal string*
GetEntryAtIndex (s32 Index, string_array Buffer)
{
string* Result = 0;
if (Buffer.Buckets)
{
bucket_index BucketIndex = GetBucketIndexForIndex(Index, Buffer.BucketSize);
Result = Buffer.Buckets[BucketIndex.Bucket] + BucketIndex.IndexInBucket;
}
return Result;
}
internal s32
PushElement (string Data, string_array* Buffer)
{
s32 Result = -1;
if (Buffer->Used >= Buffer->BucketSize * Buffer->BucketCount)
{
Buffer->Buckets = (string**)GrowBuffer(Buffer->BucketSize, sizeof(string), &Buffer->BucketCount, (void**)Buffer->Buckets);
}
s32 Index = Buffer->Used++;
s32 BucketIndex = Index / Buffer->BucketSize;
s32 IndexInBucket = Index % Buffer->BucketSize;
Buffer->Buckets[BucketIndex][IndexInBucket] = Data;
Result = Index;
return Result;
}
struct string_builder
{
string_array Buffer;
s32 BufferElementSize;
};
internal string_builder
InitStringBuilder(s32 BufferSize)
{
string_builder Result = {};
Result.BufferElementSize = BufferSize;
Result.Buffer.BucketSize = STRING_BUILDER_ARRAY_BUFFER_SIZE;
Result.Buffer.FreeList.Next = &Result.Buffer.FreeList;
return Result;
}
internal void
GrowStringBuilder (string_builder* StringBuilder)
{
string NewSegment = {};
NewSegment.Memory = (char*)malloc(StringBuilder->BufferElementSize * sizeof(char));
NewSegment.Max = StringBuilder->BufferElementSize;
PushElement(NewSegment, &StringBuilder->Buffer);
}
internal void
StringBuilderPrintF (string_builder* StringBuilder, char* Format, ...)
{
string Addition = {};
Addition.Max = 2048;
Addition.Memory = (char*)malloc(Addition.Max * sizeof(char));
va_list Args;
va_start(Args, Format);
Addition.Length = PrintFArgsList(Addition.Memory, Addition.Max, Format, Args);
s32 CharsCopied = 0;
while (CharsCopied < Addition.Length)
{
s32 StringBuilderTailIndex = StringBuilder->Buffer.Used - 1;
string* LastString = GetEntryAtIndex(StringBuilderTailIndex, StringBuilder->Buffer);
if (!LastString || LastString->Length >= LastString->Max)
{
GrowStringBuilder(StringBuilder);
StringBuilderTailIndex = StringBuilder->Buffer.Used - 1;
LastString = GetEntryAtIndex(StringBuilderTailIndex, StringBuilder->Buffer);
}
while (CharsCopied < Addition.Length && LastString->Length < LastString->Max)
{
LastString->Memory[LastString->Length++] = Addition.Memory[CharsCopied++];
}
}
free(Addition.Memory);
}