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\Platform.c" />
|
||||||
<ClCompile Include="src\Renderer.c" />
|
<ClCompile Include="src\Renderer.c" />
|
||||||
<ClCompile Include="src\Shader.c" />
|
<ClCompile Include="src\Shader.c" />
|
||||||
|
<ClCompile Include="src\String.c" />
|
||||||
<ClCompile Include="src\UserInterface.c" />
|
<ClCompile Include="src\UserInterface.c" />
|
||||||
<ClCompile Include="src\WorldTraveller.c" />
|
<ClCompile Include="src\WorldTraveller.c" />
|
||||||
<ClCompile Include="src\Texture.c" />
|
<ClCompile Include="src\Texture.c" />
|
||||||
@ -153,6 +154,7 @@
|
|||||||
<ClInclude Include="src\include\Dengine\OpenGL.h" />
|
<ClInclude Include="src\include\Dengine\OpenGL.h" />
|
||||||
<ClInclude Include="src\include\Dengine\Renderer.h" />
|
<ClInclude Include="src\include\Dengine\Renderer.h" />
|
||||||
<ClInclude Include="src\include\Dengine\Shader.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\Texture.h" />
|
||||||
<ClInclude Include="src\include\Dengine\UserInterface.h" />
|
<ClInclude Include="src\include\Dengine\UserInterface.h" />
|
||||||
<ClInclude Include="src\include\Dengine\WorldTraveller.h" />
|
<ClInclude Include="src\include\Dengine\WorldTraveller.h" />
|
||||||
|
@ -51,6 +51,9 @@
|
|||||||
<ClCompile Include="src\UserInterface.c">
|
<ClCompile Include="src\UserInterface.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\String.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="data\shaders\default.vert.glsl" />
|
<None Include="data\shaders\default.vert.glsl" />
|
||||||
@ -107,5 +110,8 @@
|
|||||||
<ClInclude Include="src\include\Dengine\UserInterface.h">
|
<ClInclude Include="src\include\Dengine\UserInterface.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\include\Dengine\String.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -39,7 +39,7 @@ char *common_strncpy(char *dest, const char *src, i32 numChars)
|
|||||||
return dest;
|
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++)
|
for (i32 i = 0; i < numBytes; i++)
|
||||||
ptr[i] = value;
|
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/Debug.h"
|
||||||
#include "Dengine/Entity.h"
|
#include "Dengine/Entity.h"
|
||||||
#include "Dengine/Platform.h"
|
#include "Dengine/Platform.h"
|
||||||
|
#include "Dengine/String.h"
|
||||||
#include "Dengine/UserInterface.h"
|
#include "Dengine/UserInterface.h"
|
||||||
|
|
||||||
enum State
|
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")) == 32);
|
||||||
ASSERT(common_atoi("+ 32", common_strlen("+ 32")) == 0);
|
ASSERT(common_atoi("+ 32", common_strlen("+ 32")) == 0);
|
||||||
asset_unitTest(arena);
|
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!
|
// 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);
|
i32 common_strcmp(const char *a, const char *b);
|
||||||
void common_strncat(char *dest, const char *src, i32 numChars);
|
void common_strncat(char *dest, const char *src, i32 numChars);
|
||||||
char *common_strncpy(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
|
// Max buffer size should be 11 for 32 bit integers
|
||||||
void common_itoa(i32 value, char *buf, i32 bufSize);
|
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