Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 29 additions & 5 deletions CoDeLib/RaiiString/src/RaiiString.c
Original file line number Diff line number Diff line change
@@ -1,21 +1,45 @@
#include <CoDeLib/RaiiString/RaiiString.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

RaiiString RaiiStringCreate(size_t length) {
RaiiString newRaiistring = {NULL, length};
newRaiistring.pString = (char *)calloc(length, sizeof(char));
RaiiString RaiiStringCreate(size_t lengthWithTermination) {
RaiiString newRaiistring = {NULL, 0};

if (lengthWithTermination == 0 ||
lengthWithTermination >= MAX_CSTRING_INCLUDING_TERMINATION_LENGTH) {
return newRaiistring;
}

newRaiistring.lengthWithTermination = lengthWithTermination;
newRaiistring.pString = (char *)calloc(lengthWithTermination, sizeof(char));
if (newRaiistring.pString == NULL) {
newRaiistring.length = 0;
newRaiistring.lengthWithTermination = 0;
printf("Failed to allocate memory for RaiiString\n");
exit(1);
}
return newRaiistring;
}

RaiiString RaiiStringCreateFromCString(const char *pCString) {
const size_t length =
strnlen(pCString, MAX_CSTRING_INCLUDING_TERMINATION_LENGTH);
RaiiString newRaiistring = RaiiStringCreate(length + 1);

if (newRaiistring.pString == NULL) {
return newRaiistring;
}

strncpy(newRaiistring.pString, pCString,
newRaiistring.lengthWithTermination - 1);
newRaiistring.pString[newRaiistring.lengthWithTermination - 1] = '\0';
return newRaiistring;
}

void RaiiStringClean(RaiiString *pThis) {
if (pThis->pString != NULL) {
free(pThis->pString);
pThis->pString = NULL;
}
}
pThis->lengthWithTermination = 0;
}
1 change: 1 addition & 0 deletions CoDeLib/Test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_executable(CoDeLib_Test
src/main.c
src/TestRaiiString.c
src/TestDeflateInflateZlib.c)

target_include_directories(CoDeLib_Test PUBLIC
Expand Down
2 changes: 1 addition & 1 deletion CoDeLib/Test/Utility/FileUtils.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ void CreateFullPathToFile(const RaiiString *pFullPath,
assert(pBasePath != NULL);
assert(pFileName != NULL);
assert(pFullPath->pString != NULL);
assert(pFullPath->length >= maxFullPathStringSize);
assert(pFullPath->lengthWithTermination >= maxFullPathStringSize);

const int charsWritten = snprintf(pFullPath->pString, maxFullPathStringSize,
"%s%s", pBasePath, pFileName);
Expand Down
175 changes: 175 additions & 0 deletions CoDeLib/Test/src/TestRaiiString.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#include "unity_fixture.h"
#include <CoDeLib/RaiiString/RaiiString.h>
#include <assert.h>
#include <string.h>

TEST_GROUP(TestRaiiString);

static RaiiString raiiString;

TEST_SETUP(TestRaiiString) {}

TEST_TEAR_DOWN(TestRaiiString) { RaiiStringClean(&raiiString); }

//==============================
// RaiiStringCreate()
//==============================

TEST(TestRaiiString, test_RaiiStringCreate_SetsCorrectsLengthInReturnedObject) {
const size_t length = 10;
raiiString = RaiiStringCreate(length);
TEST_ASSERT_EQUAL(length, raiiString.lengthWithTermination);
}

TEST(TestRaiiString, test_RaiiStringCreate_SetsNonNullPointerInReturnedObject) {
const size_t length = 10;
raiiString = RaiiStringCreate(length);
TEST_ASSERT_NOT_NULL(raiiString.pString);
}

TEST(TestRaiiString,
test_RaiiStringCreate_SetsNullptrAndLengthZeroIfGivenLengthIsZero) {
const size_t length = 0;
raiiString = RaiiStringCreate(length);
TEST_ASSERT_NULL(raiiString.pString);
TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination);
}

TEST(TestRaiiString,
test_RaiiStringCreate_SetsZeroLengthAndNullptrIfLengthIsMaxLength) {
const size_t length = MAX_CSTRING_INCLUDING_TERMINATION_LENGTH;
raiiString = RaiiStringCreate(length);
TEST_ASSERT_NULL(raiiString.pString);
TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination);
}

TEST(
TestRaiiString,
test_RaiiStringCreate_SetsZeroLengthAndNullptrIfLengthIsGreaterThanMaxLength) {
const size_t length = MAX_CSTRING_INCLUDING_TERMINATION_LENGTH + 1;
raiiString = RaiiStringCreate(length);
TEST_ASSERT_NULL(raiiString.pString);
TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination);
}

//==============================
// RaiiStringCreateFromCString()
//==============================

TEST(
TestRaiiString,
test_RaiiStringCreateFromCString_SetsLengthOfOneAndNonNullptrIfProvidedEmptyString) {
const char *pCString = "";
raiiString = RaiiStringCreateFromCString(pCString);
TEST_ASSERT_NOT_NULL(raiiString.pString);
TEST_ASSERT_EQUAL(1, raiiString.lengthWithTermination);
}

TEST(
TestRaiiString,
test_RaiiStringCreateFromCString_SetsExecptedLengthAndNonNullptrIfProvidedNormalString) {
const char *pCString = "Hello, world!";
raiiString = RaiiStringCreateFromCString(pCString);
TEST_ASSERT_NOT_NULL(raiiString.pString);
TEST_ASSERT_EQUAL(14, raiiString.lengthWithTermination);
}

TEST(TestRaiiString, test_RaiiStringCreateFromCString_SetsExecptedString) {
const char *pCString = "Hello, world!";
raiiString = RaiiStringCreateFromCString(pCString);
TEST_ASSERT_EQUAL_STRING(pCString, raiiString.pString);
}

TEST(
TestRaiiString,
test_RaiiStringCreateFromCString_DoesNotUseProvidedPointerInReturnedObject) {
const char *pCString = "";
raiiString = RaiiStringCreateFromCString(pCString);
TEST_ASSERT_NOT_EQUAL(pCString, raiiString.pString);
}

TEST(
TestRaiiString,
test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfLengthIsMaxLength) {
const size_t lengthWithNullTermination =
MAX_CSTRING_INCLUDING_TERMINATION_LENGTH + 1;
char *pCString = (char *)malloc(lengthWithNullTermination * sizeof(char));
assert(pCString != NULL && "Failed to allocate memory for pCString");
memset(pCString, 'a', lengthWithNullTermination - 1);
pCString[MAX_CSTRING_INCLUDING_TERMINATION_LENGTH] = '\0';

raiiString = RaiiStringCreateFromCString(pCString);
TEST_ASSERT_NULL(raiiString.pString);
TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination);
}

TEST(
TestRaiiString,
test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfLengthIsGreaterThanMaxLength) {
const size_t lengthWithNullTermination =
MAX_CSTRING_INCLUDING_TERMINATION_LENGTH + 2;
char *pCString = (char *)malloc(lengthWithNullTermination * sizeof(char));
assert(pCString != NULL && "Failed to allocate memory for pCString");
memset(pCString, 'a', lengthWithNullTermination - 1);
pCString[lengthWithNullTermination - 1] = '\0';

raiiString = RaiiStringCreateFromCString(pCString);
TEST_ASSERT_NULL(raiiString.pString);
TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination);
}

//==============================
// RaiiStringClean()
//==============================

TEST(TestRaiiString, test_RaiiStringClean_SetsNullptrInObject) {
raiiString = RaiiStringCreate(10);
RaiiStringClean(&raiiString);
TEST_ASSERT_NULL(raiiString.pString);
}

TEST(TestRaiiString, test_RaiiStringClean_SetsLengthZeroInObject) {
raiiString = RaiiStringCreate(10);
RaiiStringClean(&raiiString);
TEST_ASSERT_EQUAL(0, raiiString.lengthWithTermination);
}

TEST_GROUP_RUNNER(TestRaiiString) {
// RaiiStringCreate()
RUN_TEST_CASE(TestRaiiString,
test_RaiiStringCreate_SetsCorrectsLengthInReturnedObject);
RUN_TEST_CASE(TestRaiiString,
test_RaiiStringCreate_SetsNonNullPointerInReturnedObject);
RUN_TEST_CASE(
TestRaiiString,
test_RaiiStringCreate_SetsNullptrAndLengthZeroIfGivenLengthIsZero);
RUN_TEST_CASE(
TestRaiiString,
test_RaiiStringCreate_SetsZeroLengthAndNullptrIfLengthIsMaxLength);
RUN_TEST_CASE(
TestRaiiString,
test_RaiiStringCreate_SetsZeroLengthAndNullptrIfLengthIsGreaterThanMaxLength);

// RaiiStringCreateFromCString()
RUN_TEST_CASE(
TestRaiiString,
test_RaiiStringCreateFromCString_SetsLengthOfOneAndNonNullptrIfProvidedEmptyString);
RUN_TEST_CASE(
TestRaiiString,
test_RaiiStringCreateFromCString_SetsExecptedLengthAndNonNullptrIfProvidedNormalString);
RUN_TEST_CASE(TestRaiiString,
test_RaiiStringCreateFromCString_SetsExecptedString);
RUN_TEST_CASE(
TestRaiiString,
test_RaiiStringCreateFromCString_DoesNotUseProvidedPointerInReturnedObject);
RUN_TEST_CASE(
TestRaiiString,
test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfLengthIsMaxLength);
RUN_TEST_CASE(
TestRaiiString,
test_RaiiStringCreateFromCString_SetsZeroLengthAndNullptrIfLengthIsGreaterThanMaxLength);

// RaiiStringClean()
RUN_TEST_CASE(TestRaiiString, test_RaiiStringClean_SetsNullptrInObject);
RUN_TEST_CASE(TestRaiiString, test_RaiiStringClean_SetsLengthZeroInObject);
}
5 changes: 4 additions & 1 deletion CoDeLib/Test/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
#include "TestDeflateInflateZlib.h"
#include <CoDeLib/RaiiString/RaiiString.h>

static void RunAllTests(void) { RUN_TEST_GROUP(TestDeflateInflateZlib); }
static void RunAllTests(void) {
RUN_TEST_GROUP(TestRaiiString);
RUN_TEST_GROUP(TestDeflateInflateZlib);
}

int main(int argc, const char **argv) {
char *pFullPathToBenchmarkTestFiles;
Expand Down
8 changes: 7 additions & 1 deletion CoDeLib/include/CoDeLib/RaiiString/RaiiString.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@

typedef struct {
char *pString;
size_t length;

// Length of the string (including the null terminator)
size_t lengthWithTermination;
} RaiiString;

// Maximum length of a C string (including the null terminator)
static const size_t MAX_CSTRING_INCLUDING_TERMINATION_LENGTH = 1024;

RaiiString RaiiStringCreate(size_t length);
RaiiString RaiiStringCreateFromCString(const char *pCString);
void RaiiStringClean(RaiiString *pThis);