Add draft better string library implementation
This commit is contained in:
parent
da07ce3f75
commit
5b682ddcf6
@ -129,6 +129,7 @@
|
||||
<ClCompile Include="src\Platform.c" />
|
||||
<ClCompile Include="src\Renderer.c" />
|
||||
<ClCompile Include="src\Shader.c" />
|
||||
<ClCompile Include="src\String.c" />
|
||||
<ClCompile Include="src\UserInterface.c" />
|
||||
<ClCompile Include="src\WorldTraveller.c" />
|
||||
<ClCompile Include="src\Texture.c" />
|
||||
@ -153,6 +154,7 @@
|
||||
<ClInclude Include="src\include\Dengine\OpenGL.h" />
|
||||
<ClInclude Include="src\include\Dengine\Renderer.h" />
|
||||
<ClInclude Include="src\include\Dengine\Shader.h" />
|
||||
<ClInclude Include="src\include\Dengine\String.h" />
|
||||
<ClInclude Include="src\include\Dengine\Texture.h" />
|
||||
<ClInclude Include="src\include\Dengine\UserInterface.h" />
|
||||
<ClInclude Include="src\include\Dengine\WorldTraveller.h" />
|
||||
|
@ -51,6 +51,9 @@
|
||||
<ClCompile Include="src\UserInterface.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\String.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="data\shaders\default.vert.glsl" />
|
||||
@ -107,5 +110,8 @@
|
||||
<ClInclude Include="src\include\Dengine\UserInterface.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\include\Dengine\String.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -39,7 +39,7 @@ char *common_strncpy(char *dest, const char *src, i32 numChars)
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *common_memset(char *const ptr, const i32 value, const i32 numBytes)
|
||||
u8 *common_memset(u8 *const ptr, const i32 value, const i32 numBytes)
|
||||
{
|
||||
for (i32 i = 0; i < numBytes; i++)
|
||||
ptr[i] = value;
|
||||
|
117
src/String.c
Normal file
117
src/String.c
Normal file
@ -0,0 +1,117 @@
|
||||
#include "Dengine/String.h"
|
||||
#include "Dengine/Platform.h"
|
||||
|
||||
/*
|
||||
* +-------------------------------------+
|
||||
* | Header | C-String | Null Terminator |
|
||||
* +-------------------------------------+
|
||||
* |
|
||||
* +--> Functions return the c-string for compatibility with other
|
||||
* string libraries
|
||||
*
|
||||
* Headers are retrieved using pointer arithmetric from the C string. These
|
||||
* strings are typechecked by their own typedef char String.
|
||||
*/
|
||||
|
||||
typedef struct StringHeader
|
||||
{
|
||||
i32 len;
|
||||
|
||||
// NOTE(doyle): A string is stored as one contiguous chunk of memory. We
|
||||
// don't use a pointer for storing the string as this'd require an extra
|
||||
// 4 bytes to store the pointer, which we don't need if everything is
|
||||
// contiguous. The string follows on from the len, and we return the address
|
||||
// of the string to simulate a pointer.
|
||||
String string;
|
||||
} StringHeader;
|
||||
|
||||
// TODO(doyle): string capacity- append if already enough space
|
||||
INTERNAL StringHeader *string_getHeader(String *const string)
|
||||
{
|
||||
StringHeader *result = NULL;
|
||||
|
||||
// NOTE(doyle): C-String must be located at end of struct type for offset to
|
||||
// be correct! We cannot just subtract the string-header since we start at
|
||||
// the string ptr position
|
||||
if (string)
|
||||
{
|
||||
i32 byteOffsetToHeader = sizeof(StringHeader) - sizeof(String *);
|
||||
result = CAST(StringHeader *)((CAST(u8 *) string) - byteOffsetToHeader);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
i32 string_len(String *const string)
|
||||
{
|
||||
if (!string) return -1;
|
||||
|
||||
StringHeader *header = string_getHeader(string);
|
||||
i32 result = header->len;
|
||||
return result;
|
||||
}
|
||||
|
||||
String *const string_append(MemoryArena *const arena, String *oldString,
|
||||
char *appendString, i32 appendLen)
|
||||
|
||||
{
|
||||
if (!oldString || !appendString || !arena) return oldString;
|
||||
|
||||
/* Calculate size of new string */
|
||||
StringHeader *oldHeader = string_getHeader(oldString);
|
||||
i32 newLen = oldHeader->len + appendLen;
|
||||
String *newString = string_makeLen(arena, newLen);
|
||||
|
||||
/* Append strings together */
|
||||
String *insertPtr = newString;
|
||||
common_strncpy(insertPtr, oldString, oldHeader->len);
|
||||
insertPtr += oldHeader->len;
|
||||
common_strncpy(insertPtr, appendString, appendLen);
|
||||
|
||||
/* Free old string */
|
||||
string_free(arena, oldString);
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
void string_free(MemoryArena *arena, String *string)
|
||||
{
|
||||
if (!string || !arena) return;
|
||||
|
||||
StringHeader *header = string_getHeader(string);
|
||||
i32 bytesToFree = sizeof(StringHeader) + header->len;
|
||||
|
||||
common_memset((u8 *)header, 0, bytesToFree);
|
||||
PLATFORM_MEM_FREE(arena, header, bytesToFree);
|
||||
string = NULL;
|
||||
}
|
||||
|
||||
String *const string_make(MemoryArena *const arena, char *string)
|
||||
{
|
||||
if (!arena) return NULL;
|
||||
|
||||
i32 len = common_strlen(string);
|
||||
String *result = string_makeLen(arena, len);
|
||||
common_strncpy(result, string, len);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String *const string_makeLen(MemoryArena *const arena, i32 len)
|
||||
{
|
||||
if (!arena) return NULL;
|
||||
|
||||
// NOTE(doyle): Allocate the string header size plus the len. But _note_
|
||||
// that StringHeader contains a single String character. This has
|
||||
// a side-effect of already preallocating a byte for the null-terminating
|
||||
// character. Whilst the len of a string counts up to the last character
|
||||
// _not_ including null-terminator.
|
||||
i32 bytesToAllocate = sizeof(StringHeader) + len;
|
||||
void *chunk = PLATFORM_MEM_ALLOC(arena, bytesToAllocate, u8);
|
||||
if (!chunk) return NULL;
|
||||
|
||||
StringHeader *header = CAST(StringHeader *) chunk;
|
||||
header->len = len;
|
||||
return &header->string;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Dengine/Debug.h"
|
||||
#include "Dengine/Entity.h"
|
||||
#include "Dengine/Platform.h"
|
||||
#include "Dengine/String.h"
|
||||
#include "Dengine/UserInterface.h"
|
||||
|
||||
enum State
|
||||
@ -575,6 +576,30 @@ INTERNAL void unitTest(MemoryArena *arena)
|
||||
ASSERT(common_atoi("+32", common_strlen("+32")) == 32);
|
||||
ASSERT(common_atoi("+ 32", common_strlen("+ 32")) == 0);
|
||||
asset_unitTest(arena);
|
||||
|
||||
i32 memBefore = arena->bytesAllocated;
|
||||
String *hello = string_make(arena, "hello, ");
|
||||
String *world = string_make(arena, "world");
|
||||
ASSERT(string_len(hello) == 7);
|
||||
ASSERT(string_len(world) == 5);
|
||||
|
||||
hello = string_append(arena, hello, world, string_len(world));
|
||||
ASSERT(string_len(hello) == 12);
|
||||
string_free(arena, hello);
|
||||
string_free(arena, world);
|
||||
|
||||
hello = string_make(arena, "");
|
||||
world = string_make(arena, "");
|
||||
hello = string_append(arena, hello, world, string_len(world));
|
||||
ASSERT(string_len(hello) == 0);
|
||||
ASSERT(string_len(world) == 0);
|
||||
|
||||
string_free(arena, hello);
|
||||
string_free(arena, world);
|
||||
|
||||
i32 memAfter = arena->bytesAllocated;
|
||||
|
||||
ASSERT(memBefore == memAfter);
|
||||
}
|
||||
|
||||
// TODO(doyle): Remove and implement own random generator!
|
||||
|
@ -32,7 +32,7 @@ i32 common_strlen(const char *const string);
|
||||
i32 common_strcmp(const char *a, const char *b);
|
||||
void common_strncat(char *dest, const char *src, i32 numChars);
|
||||
char *common_strncpy(char *dest, const char *src, i32 numChars);
|
||||
char *common_memset(char *const ptr, const i32 value, const i32 numBytes);
|
||||
u8 *common_memset(u8 *const ptr, const i32 value, const i32 numBytes);
|
||||
|
||||
// Max buffer size should be 11 for 32 bit integers
|
||||
void common_itoa(i32 value, char *buf, i32 bufSize);
|
||||
|
17
src/include/Dengine/String.h
Normal file
17
src/include/Dengine/String.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef DENGINE_STRING_H
|
||||
#define DENGINE_STRING_H
|
||||
|
||||
#include "Dengine/Common.h"
|
||||
|
||||
typedef struct MemoryArena MemoryArena;
|
||||
|
||||
typedef char String;
|
||||
|
||||
i32 string_len(String *const string);
|
||||
String *const string_append(MemoryArena *const arena, String *oldString,
|
||||
String *appendString, i32 appendLen);
|
||||
void string_free(MemoryArena *arena, String *string);
|
||||
String *const string_make(MemoryArena *const arena, char *string);
|
||||
String *const string_makeLen(MemoryArena *const arena, i32 len);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user