99 lines
2.7 KiB
C
99 lines
2.7 KiB
C
#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);
|
|
} |