diff --git a/code/logic/cstring.c b/code/logic/cstring.c index 244b1cf..5ead8c9 100644 --- a/code/logic/cstring.c +++ b/code/logic/cstring.c @@ -15,6 +15,7 @@ #include "fossil/io/output.h" #include #include +#include // ============================================================================ // C String Functions @@ -36,6 +37,238 @@ void fossil_io_cstring_free(cstring str) { } } +int fossil_io_cstring_silly(const char *input, char *output, size_t size) { + if (!input || !output || size == 0) return -1; + + size_t len = strlen(input); + if (len + 1 > size) return -1; + + for (size_t i = 0; i < len; i++) { + char c = input[i]; + // Random case change + if (isalpha((unsigned char)c)) { + if (rand() % 2) { + c = (char)toupper((unsigned char)c); + } else { + c = (char)tolower((unsigned char)c); + } + } + // Occasionally insert silly symbol + if (rand() % 10 == 0 && (i + 1 < size - 1)) { + output[i++] = '~'; + } + output[i] = c; + } + output[len] = '\0'; + return 0; +} + +int fossil_io_cstring_piglatin(const char *input, char *output, size_t size) { + if (!input || !output || size == 0) return -1; + + output[0] = '\0'; + const char *delims = " \t\n"; + char buffer[256]; + char word[128]; + + // Copy input safely into a working buffer + strncpy(buffer, input, sizeof(buffer) - 1); + buffer[sizeof(buffer) - 1] = '\0'; + + char *token = strtok(buffer, delims); + while (token) { + size_t word_len = strlen(token); + if (word_len == 0) { + token = strtok(NULL, delims); + continue; + } + + // Vowel start → add "yay" + if (strchr("AEIOUaeiou", token[0])) { + strncpy(word, token, sizeof(word) - 4); // leave room for "yay" + word[sizeof(word) - 4] = '\0'; + strncat(word, "yay", sizeof(word) - strlen(word) - 1); + } + // Consonant start → move first letter, add "ay" + else { + strncpy(word, token + 1, sizeof(word) - 4); // leave room for "ay" + word[sizeof(word) - 4] = '\0'; + + size_t len = strlen(word); + if (len < sizeof(word) - 3) { + word[len] = token[0]; + word[len + 1] = 'a'; + word[len + 2] = 'y'; + word[len + 3] = '\0'; + } else { + return -1; // truncated + } + } + + // Check space in output before appending + if (strlen(output) + strlen(word) + 2 > size) return -1; + strcat(output, word); + strcat(output, " "); + + token = strtok(NULL, delims); + } + + return 0; +} + +int fossil_io_cstring_leetspeak(const char *input, char *output, size_t size) { + if (!input || !output || size == 0) return -1; + + size_t out_idx = 0; + for (size_t i = 0; input[i] && out_idx < size - 1; i++) { + char c = input[i]; + char repl[3] = {0}; + + switch (tolower((unsigned char)c)) { + case 'a': strcpy(repl, "4"); break; + case 'e': strcpy(repl, "3"); break; + case 'i': strcpy(repl, "1"); break; + case 'o': strcpy(repl, "0"); break; + case 's': strcpy(repl, "5"); break; + case 't': strcpy(repl, "7"); break; + default: repl[0] = c; repl[1] = '\0'; break; + } + + size_t repl_len = strlen(repl); + if (out_idx + repl_len >= size - 1) return -1; + strcpy(&output[out_idx], repl); + out_idx += repl_len; + } + output[out_idx] = '\0'; + return 0; +} + +// ------------------- +// Mocking SpongeBob +// ------------------- +char* fossil_io_cstring_mocking(const char *str) { + if (!str) return NULL; + size_t len = strlen(str); + char *out = malloc(len + 1); + if (!out) return NULL; + + for (size_t i = 0; i < len; i++) { + if (i % 2 == 0) + out[i] = tolower((unsigned char)str[i]); + else + out[i] = toupper((unsigned char)str[i]); + } + out[len] = '\0'; + return out; +} + +// ------------------- +// ROT13 Cipher +// ------------------- +char* fossil_io_cstring_rot13(const char *str) { + if (!str) return NULL; + size_t len = strlen(str); + char *out = malloc(len + 1); + if (!out) return NULL; + + for (size_t i = 0; i < len; i++) { + char c = str[i]; + if ('a' <= c && c <= 'z') + out[i] = ((c - 'a' + 13) % 26) + 'a'; + else if ('A' <= c && c <= 'Z') + out[i] = ((c - 'A' + 13) % 26) + 'A'; + else + out[i] = c; + } + out[len] = '\0'; + return out; +} + +// ------------------- +// Shuffle String +// ------------------- +char* fossil_io_cstring_shuffle(const char *str) { + if (!str) return NULL; + size_t len = strlen(str); + char *out = malloc(len + 1); + if (!out) return NULL; + + strcpy(out, str); + + // Seed RNG once per run + static int seeded = 0; + if (!seeded) { + srand((unsigned int)time(NULL)); + seeded = 1; + } + + for (size_t i = 0; i < len; i++) { + size_t j = rand() % len; + char tmp = out[i]; + out[i] = out[j]; + out[j] = tmp; + } + + return out; +} + +// ------------------- +// UPPER_SNAKE_CASE +// ------------------- +char* fossil_io_cstring_upper_snake(const char *str) { + if (!str) return NULL; + size_t len = strlen(str); + + // Worst case: every char becomes "_X" + char *out = malloc(len * 2 + 1); + if (!out) return NULL; + + size_t j = 0; + for (size_t i = 0; i < len; i++) { + if (isspace((unsigned char)str[i])) { + out[j++] = '_'; + } else if (isalpha((unsigned char)str[i])) { + out[j++] = toupper((unsigned char)str[i]); + } else { + out[j++] = str[i]; + } + } + out[j] = '\0'; + return out; +} + +// ------------------- +// Zalgo Text (simplified) +// ------------------- +char* fossil_io_cstring_zalgo(const char *str) { + if (!str) return NULL; + size_t len = strlen(str); + + // Each char may get up to 3 combining marks + char *out = malloc(len * 10 + 1); + if (!out) return NULL; + + static const char *zalgo_marks[] = { + "\u0300", "\u0301", "\u0302", "\u0303", "\u0304", + "\u0306", "\u0307", "\u0308", "\u030A", "\u0315", + "\u0327", "\u0328", "\u0334", "\u033F", "\u0346" + }; + static const size_t num_marks = sizeof(zalgo_marks) / sizeof(zalgo_marks[0]); + + size_t j = 0; + for (size_t i = 0; i < len; i++) { + j += sprintf(out + j, "%c", str[i]); + + int marks = rand() % 3; // 0–2 zalgo marks + for (int m = 0; m < marks; m++) { + const char *mark = zalgo_marks[rand() % num_marks]; + j += sprintf(out + j, "%s", mark); + } + } + out[j] = '\0'; + return out; +} + cstring fossil_io_cstring_copy(ccstring str) { if (!str) return NULL; return fossil_io_cstring_create(str); diff --git a/code/logic/fossil/io/cstring.h b/code/logic/fossil/io/cstring.h index 2c692c8..186cff6 100644 --- a/code/logic/fossil/io/cstring.h +++ b/code/logic/fossil/io/cstring.h @@ -49,6 +49,95 @@ cstring fossil_io_cstring_create(const char *init); */ void fossil_io_cstring_free(cstring str); +/** + * @brief Converts input into a "silly" string (random case and symbols). + * + * @param input The input string. + * @param output The buffer for the transformed string. + * @param size The size of the output buffer. + * @return 0 on success, non-zero on error (buffer too small). + */ +int fossil_io_cstring_silly(const char *input, char *output, size_t size); + +/** + * @brief Converts input into Pig Latin. + * + * Rules: + * - Words starting with a vowel → add "yay" at the end. + * - Words starting with consonant(s) → move leading consonant(s) to the end + "ay". + * + * @param input The input string. + * @param output The buffer for the transformed string. + * @param size The size of the output buffer. + * @return 0 on success, non-zero on error. + */ +int fossil_io_cstring_piglatin(const char *input, char *output, size_t size); + +/** + * @brief Converts input into "leet speak". + * + * Mapping (basic): + * A → 4, E → 3, I → 1, O → 0, S → 5, T → 7 + * + * @param input The input string. + * @param output The buffer for the transformed string. + * @param size The size of the output buffer. + * @return 0 on success, non-zero on error. + */ +int fossil_io_cstring_leetspeak(const char *input, char *output, size_t size); + +// Novelty String Transforms + +/** + * @brief Converts a string into "mocking SpongeBob" case. + * + * Example: "hello world" -> "hElLo wOrLd" + * + * @param str Input string. + * @return Newly allocated transformed string, or NULL on failure. + */ +char* fossil_io_cstring_mocking(const char *str); + +/** + * @brief Applies ROT13 cipher to a string. + * + * Example: "hello" -> "uryyb" + * + * @param str Input string. + * @return Newly allocated transformed string, or NULL on failure. + */ +char* fossil_io_cstring_rot13(const char *str); + +/** + * @brief Shuffles the characters of a string randomly. + * + * Example: "hello" -> "lohel" (result varies). + * + * @param str Input string. + * @return Newly allocated shuffled string, or NULL on failure. + */ +char* fossil_io_cstring_shuffle(const char *str); + +/** + * @brief Converts a string to UPPER_SNAKE_CASE. + * + * Example: "Hello World" -> "HELLO_WORLD" + * + * @param str Input string. + * @return Newly allocated transformed string, or NULL on failure. + */ +char* fossil_io_cstring_upper_snake(const char *str); + +/** + * @brief Generates a "zalgo" glitch text version of a string. + * + * Example: "hello" -> "h̶͋̓e̸͆̀l̷͛̕l̶͛̀o̴̓̕" + * + * @param str Input string. + * @return Newly allocated transformed string, or NULL on failure. + */ +char* fossil_io_cstring_zalgo(const char *str); + /** * @brief Creates a copy of the given cstring. * @@ -500,6 +589,93 @@ namespace fossil { return CString(fossil_io_cstring_copy(str.c_str())); } + /** + * Converts input into a "silly" string (random case and symbols). + * + * @param output_size The size of the output buffer. + * @return A std::string with the silly transformation. + */ + std::string silly(size_t output_size = 256) const { + char *output = new char[output_size]; + int res = fossil_io_cstring_silly(_str, output, output_size); + std::string result = (res == 0) ? std::string(output) : ""; + delete[] output; + return result; + } + + /** + * Converts input into Pig Latin. + * + * @param output_size The size of the output buffer. + * @return A std::string with the Pig Latin transformation. + */ + std::string piglatin(size_t output_size = 256) const { + char *output = new char[output_size]; + int res = fossil_io_cstring_piglatin(_str, output, output_size); + std::string result = (res == 0) ? std::string(output) : ""; + delete[] output; + return result; + } + + /** + * Converts input into "leet speak". + * + * @param output_size The size of the output buffer. + * @return A std::string with the leet speak transformation. + */ + std::string leetspeak(size_t output_size = 256) const { + char *output = new char[output_size]; + int res = fossil_io_cstring_leetspeak(_str, output, output_size); + std::string result = (res == 0) ? std::string(output) : ""; + delete[] output; + return result; + } + + /** + * Converts a string into "mocking SpongeBob" case. + * + * @return A CString with the mocking transformation. + */ + CString mocking() const { + return CString(fossil_io_cstring_mocking(_str)); + } + + /** + * Applies ROT13 cipher to a string. + * + * @return A CString with the ROT13 transformation. + */ + CString rot13() const { + return CString(fossil_io_cstring_rot13(_str)); + } + + /** + * Shuffles the characters of a string randomly. + * + * @return A CString with the shuffled string. + */ + CString shuffle() const { + return CString(fossil_io_cstring_shuffle(_str)); + } + + /** + * Converts a string to UPPER_SNAKE_CASE. + * + * @return A CString with the UPPER_SNAKE_CASE transformation. + */ + CString upper_snake() const { + return CString(fossil_io_cstring_upper_snake(_str)); + } + + /** + * Generates a "zalgo" glitch text version of a string. + * + * @return A CString with the zalgo transformation. + */ + CString zalgo() const { + return CString(fossil_io_cstring_zalgo(_str)); + } + /** * Duplicates the given cstring. * diff --git a/code/tests/cases/test_cstring.c b/code/tests/cases/test_cstring.c index aa818c9..23b4b53 100644 --- a/code/tests/cases/test_cstring.c +++ b/code/tests/cases/test_cstring.c @@ -355,6 +355,144 @@ FOSSIL_TEST(c_test_cstring_append) { fossil_io_cstring_free(str); } +FOSSIL_TEST(c_test_cstring_silly_basic) { + char input[] = "Hello World"; + char output[64]; + int rc = fossil_io_cstring_silly(input, output, sizeof(output)); + ASSUME_ITS_EQUAL_I32(0, rc); + // Output should have same letters, possibly with random case and ~ symbols + ASSUME_ITS_TRUE(strlen(output) >= strlen(input)); + // Should contain all input letters (case-insensitive) + for (size_t i = 0; i < strlen(input); ++i) { + if (isalpha(input[i])) { + ASSUME_ITS_TRUE(strchr(output, tolower(input[i])) || strchr(output, toupper(input[i]))); + } + } +} + +FOSSIL_TEST(c_test_cstring_silly_buffer_too_small) { + char input[] = "Hello"; + char output[4]; // Too small + int rc = fossil_io_cstring_silly(input, output, sizeof(output)); + ASSUME_ITS_TRUE(rc != 0); +} + +FOSSIL_TEST(c_test_cstring_piglatin_vowel_start) { + char input[] = "apple"; + char output[64]; + int rc = fossil_io_cstring_piglatin(input, output, sizeof(output)); + ASSUME_ITS_EQUAL_I32(0, rc); + ASSUME_ITS_TRUE(strstr(output, "appleyay") != NULL); +} + +FOSSIL_TEST(c_test_cstring_piglatin_consonant_start) { + char input[] = "banana"; + char output[64]; + int rc = fossil_io_cstring_piglatin(input, output, sizeof(output)); + ASSUME_ITS_EQUAL_I32(0, rc); + ASSUME_ITS_TRUE(strstr(output, "ananabay") != NULL); +} + +FOSSIL_TEST(c_test_cstring_piglatin_multiple_words) { + char input[] = "eat banana"; + char output[64]; + int rc = fossil_io_cstring_piglatin(input, output, sizeof(output)); + ASSUME_ITS_EQUAL_I32(0, rc); + ASSUME_ITS_TRUE(strstr(output, "eatyay") != NULL); + ASSUME_ITS_TRUE(strstr(output, "ananabay") != NULL); +} + +FOSSIL_TEST(c_test_cstring_piglatin_buffer_too_small) { + char input[] = "banana"; + char output[4]; // Too small + int rc = fossil_io_cstring_piglatin(input, output, sizeof(output)); + ASSUME_ITS_TRUE(rc != 0); +} + +FOSSIL_TEST(c_test_cstring_leetspeak_basic) { + char input[] = "Test Aisle"; + char output[64]; + int rc = fossil_io_cstring_leetspeak(input, output, sizeof(output)); + ASSUME_ITS_EQUAL_I32(0, rc); + // Should contain mapped chars + ASSUME_ITS_TRUE(strchr(output, '7') != NULL); // T->7 + ASSUME_ITS_TRUE(strchr(output, '4') != NULL); // A->4 + ASSUME_ITS_TRUE(strchr(output, '1') != NULL); // I->1 + ASSUME_ITS_TRUE(strchr(output, '5') != NULL); // S->5 + ASSUME_ITS_TRUE(strchr(output, '3') != NULL); // E->3 +} + +FOSSIL_TEST(c_test_cstring_leetspeak_buffer_too_small) { + char input[] = "leet"; + char output[2]; // Too small + int rc = fossil_io_cstring_leetspeak(input, output, sizeof(output)); + ASSUME_ITS_TRUE(rc != 0); +} + +FOSSIL_TEST(c_test_cstring_mocking_basic) { + char *result = fossil_io_cstring_mocking("hello world"); + ASSUME_NOT_CNULL(result); + // Should alternate case + ASSUME_ITS_EQUAL_CSTR("hElLo wOrLd", result); + fossil_io_cstring_free(result); +} + +FOSSIL_TEST(c_test_cstring_mocking_empty) { + char *result = fossil_io_cstring_mocking(""); + ASSUME_NOT_CNULL(result); + ASSUME_ITS_EQUAL_CSTR("", result); + fossil_io_cstring_free(result); +} + +FOSSIL_TEST(c_test_cstring_rot13_basic) { + char *result = fossil_io_cstring_rot13("hello"); + ASSUME_NOT_CNULL(result); + ASSUME_ITS_EQUAL_CSTR("uryyb", result); + fossil_io_cstring_free(result); +} + +FOSSIL_TEST(c_test_cstring_rot13_twice_is_original) { + char *input = "TestString"; + char *rot = fossil_io_cstring_rot13(input); + char *rot2 = fossil_io_cstring_rot13(rot); + ASSUME_NOT_CNULL(rot); + ASSUME_NOT_CNULL(rot2); + ASSUME_ITS_EQUAL_CSTR(input, rot2); + fossil_io_cstring_free(rot); + fossil_io_cstring_free(rot2); +} + +FOSSIL_TEST(c_test_cstring_shuffle_basic) { + char *input = "abcdef"; + char *result = fossil_io_cstring_shuffle(input); + ASSUME_NOT_CNULL(result); + // Should be permutation of input + ASSUME_ITS_EQUAL_SIZE(strlen(input), strlen(result)); + fossil_io_cstring_free(result); +} + +FOSSIL_TEST(c_test_cstring_upper_snake_basic) { + char *result = fossil_io_cstring_upper_snake("Hello World"); + ASSUME_NOT_CNULL(result); + ASSUME_ITS_EQUAL_CSTR("HELLO_WORLD", result); + fossil_io_cstring_free(result); +} + +FOSSIL_TEST(c_test_cstring_upper_snake_with_symbols) { + char *result = fossil_io_cstring_upper_snake("Hello, World!"); + ASSUME_NOT_CNULL(result); + ASSUME_ITS_EQUAL_CSTR("HELLO,_WORLD!", result); + fossil_io_cstring_free(result); +} + +FOSSIL_TEST(c_test_cstring_zalgo_basic) { + char *result = fossil_io_cstring_zalgo("hello"); + ASSUME_NOT_CNULL(result); + // Should start with 'h' and contain combining marks + ASSUME_ITS_TRUE(result[0] == 'h'); + fossil_io_cstring_free(result); +} + // Test fossil_io_cstring_number_from_words FOSSIL_TEST(c_test_cstring_number_from_words) { int value = 0; @@ -423,7 +561,22 @@ FOSSIL_TEST_GROUP(c_string_tests) { FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_normalize_spaces); FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_strip_quotes); FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_append); - + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_silly_basic); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_silly_buffer_too_small); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_piglatin_vowel_start); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_piglatin_consonant_start); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_piglatin_multiple_words); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_piglatin_buffer_too_small); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_leetspeak_basic); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_leetspeak_buffer_too_small); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_mocking_basic); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_mocking_empty); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_rot13_basic); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_rot13_twice_is_original); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_shuffle_basic); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_upper_snake_basic); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_upper_snake_with_symbols); + FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_zalgo_basic); FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_number_from_words); FOSSIL_TEST_ADD(c_string_suite, c_test_cstring_number_to_words); diff --git a/code/tests/cases/test_cstring.cpp b/code/tests/cases/test_cstring.cpp index 726cc4d..41095bf 100644 --- a/code/tests/cases/test_cstring.cpp +++ b/code/tests/cases/test_cstring.cpp @@ -593,6 +593,62 @@ FOSSIL_TEST(cpp_test_cstring_class_append) { ASSUME_ITS_EQUAL_CSTR("Hello, World!", str.str()); } +FOSSIL_TEST(cpp_test_cstring_class_silly) { + fossil::io::CString str("Hello, World!"); + std::string silly = str.silly(); + ASSUME_NOT_CNULL(silly.c_str()); + ASSUME_ITS_TRUE(silly.length() > 0); +} + +FOSSIL_TEST(cpp_test_cstring_class_piglatin) { + fossil::io::CString str("Hello, World!"); + std::string pig = str.piglatin(); + ASSUME_NOT_CNULL(pig.c_str()); + ASSUME_ITS_TRUE(pig.length() > 0); +} + +FOSSIL_TEST(cpp_test_cstring_class_leetspeak) { + fossil::io::CString str("Hello, World!"); + std::string leet = str.leetspeak(); + ASSUME_NOT_CNULL(leet.c_str()); + ASSUME_ITS_TRUE(leet.length() > 0); +} + +FOSSIL_TEST(cpp_test_cstring_class_mocking) { + fossil::io::CString str("Hello, World!"); + fossil::io::CString mocking = str.mocking(); + ASSUME_NOT_CNULL(mocking.str()); + ASSUME_ITS_TRUE(mocking.length() == str.length()); +} + +FOSSIL_TEST(cpp_test_cstring_class_rot13) { + fossil::io::CString str("Hello, World!"); + fossil::io::CString rot = str.rot13(); + ASSUME_NOT_CNULL(rot.str()); + ASSUME_ITS_TRUE(rot.length() == str.length()); +} + +FOSSIL_TEST(cpp_test_cstring_class_shuffle) { + fossil::io::CString str("Hello, World!"); + fossil::io::CString shuffled = str.shuffle(); + ASSUME_NOT_CNULL(shuffled.str()); + ASSUME_ITS_TRUE(shuffled.length() == str.length()); +} + +FOSSIL_TEST(cpp_test_cstring_class_upper_snake) { + fossil::io::CString str("Hello World Fossil"); + fossil::io::CString snake = str.upper_snake(); + ASSUME_NOT_CNULL(snake.str()); + ASSUME_ITS_TRUE(std::string(snake.str()).find('_') != std::string::npos); +} + +FOSSIL_TEST(cpp_test_cstring_class_zalgo) { + fossil::io::CString str("Hello, World!"); + fossil::io::CString zalgo = str.zalgo(); + ASSUME_NOT_CNULL(zalgo.str()); + ASSUME_ITS_TRUE(zalgo.length() >= str.length()); +} + FOSSIL_TEST(cpp_test_cstring_number_from_words_basic) { int value = 0; ASSUME_ITS_EQUAL_I32(0, fossil_io_cstring_number_from_words("zero", &value)); @@ -721,6 +777,15 @@ FOSSIL_TEST_GROUP(cpp_string_tests) { FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_stream_multiple_writes); FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_stream_empty_read); + FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_silly); + FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_piglatin); + FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_leetspeak); + FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_mocking); + FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_rot13); + FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_shuffle); + FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_upper_snake); + FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_zalgo); + FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_create_and_free); FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_copy); FOSSIL_TEST_ADD(cpp_string_suite, cpp_test_cstring_class_concat);