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
92 changes: 78 additions & 14 deletions code/logic/fossil/io/soap.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,93 @@ extern "C" {
void fossil_soap_sanitize(char *input);

/**
* Check if a word is a curse word or racist phrase.
* This function checks whether a given word is considered offensive.
* It compares the word against a predefined list of offensive words and phrases
* to determine its offensiveness.
*
* @param word The word to be checked for offensiveness.
* @return True if the word is offensive, false otherwise.
* Check if a word is an offensive word or phrase.
* Returns EXIT_FAILURE if the word is considered offensive, EXIT_SUCCESS otherwise.
*/
int32_t fossil_soap_is_offensive(const char *word);

/**
* Get the number of offensive words found in a string.
* This function counts the number of offensive words found in the input string.
* It scans the entire string and checks each word against a list of offensive words
* to determine the count of offensive occurrences.
*
* @param input The input string to be checked for offensive words.
* @return The number of offensive words found.
* Check if a word is meme speak.
* Returns EXIT_FAILURE if the word is considered meme speak, EXIT_SUCCESS otherwise.
*/
int32_t fossil_soap_is_rotbrain(const char *word);

/**
* Count offensive words in a string.
* Returns the number of offensive words found in the input string.
*/
int32_t fossil_soap_count_offensive(const char *input);

/**
* Count meme speak words in a string.
* Returns the number of meme speak words found in the input string.
*/
int32_t fossil_soap_count_rotbrain(const char *input);

#ifdef __cplusplus
}

/**
* C++ wrapper for the SOAP API.
*/
namespace fossil {

/**
* Namespace for I/O operations.
*/
namespace io {
/**
* SOAP API for sanitizing strings.
*/
class Soap {
public:
/**
* Sanitize a string by replacing curse words with asterisks.
* This function scans the input string for offensive words and replaces them with asterisks,
* thereby making the string suitable for use in contexts where offensive language is not allowed.
* The input string is modified in place.
*
* @param input The input string to be sanitized in-place.
*/
static void sanitize(char *input) {
fossil_soap_sanitize(input);
}

/**
* Check if a word is an offensive word or phrase.
* Returns EXIT_FAILURE if the word is considered offensive, EXIT_SUCCESS otherwise.
*/
static int32_t is_offensive(const char *word) {
return fossil_soap_is_offensive(word);
}

/**
* Check if a word is meme speak.
* Returns EXIT_FAILURE if the word is considered meme speak, EXIT_SUCCESS otherwise.
*/
static int32_t is_rotbrain(const char *word) {
return fossil_soap_is_rotbrain(word);
}

/**
* Count offensive words in a string.
* Returns the number of offensive words found in the input string.
*/
static int32_t count_offensive(const char *input) {
return fossil_soap_count_offensive(input);
}

/**
* Count meme speak words in a string.
* Returns the number of meme speak words found in the input string.
*/
static int32_t count_rotbrain(const char *input) {
return fossil_soap_count_rotbrain(input);
}
};
}
}

#endif

#endif /* FOSSIL_IO_FRAMEWORK_H */
71 changes: 58 additions & 13 deletions code/logic/soap.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <stdlib.h>

// List of offensive words and phrases (super hard to mainting thisw list as GitHub Copilot doesnt wanna help with this part of the SOAP API)
static const char *offensive_words[] = {
static const char *FOSSIL_SOAP_OFFENSIVE[] = {
"curse1",
"curse2",
"racist_phrase1",
Expand Down Expand Up @@ -55,7 +55,18 @@ static const char *offensive_words[] = {
// Support for other languages can be added via PR to this repository
};

static inline char* _custom_fossil_strdup(const char* str) {
// garbage words and phrases
// (slightly easier to maintain since it's just slang from social media spoken from people who need to touch grass)
static const char *FOSSIL_SOAP_ROTBRAIN[] = {
"rizz", "skibidi", "yeet", "sus", "vibe", "lit", "no cap", "bet", "fam", "bruh",
"flex", "ghost", "goat", "gucci", "hype", "janky", "lowkey", "mood", "salty", "shade",
"slay", "snatched", "stan", "tea", "thirsty", "woke", "yolo", "zaddy", "drip", "fire",
"lol", "omg", "brb", "sus"

// Support for other terms can be added via PR to this repository
};

static inline char* custom_strdup(const char* str) {
if (!str) return NULL; // Handle NULL pointer gracefully

size_t len = 0;
Expand Down Expand Up @@ -90,7 +101,7 @@ static char *custom_strcasestr(const char *haystack, const char *needle) {
// Function to replace a substring in a string (case-insensitive)
static void replace_substring_case_insensitive(char *str, const char *old_substr, const char *new_substr) {
char *position = custom_strcasestr(str, old_substr);
if (position != NULL) {
while (position != NULL) {
size_t old_len = strlen(old_substr);
size_t new_len = strlen(new_substr);
size_t tail_len = strlen(position + old_len);
Expand All @@ -100,28 +111,33 @@ static void replace_substring_case_insensitive(char *str, const char *old_substr
memmove(position + new_len, position + old_len, tail_len + 1);
} else {
memmove(position + new_len, position + old_len, tail_len + 1);
memcpy(position, new_substr, new_len);
}
memcpy(position, new_substr, new_len);

// Find the next occurrence
position = custom_strcasestr(position + new_len, old_substr);
}
}

void fossil_soap_sanitize(char *input) {
if (input == NULL || *input == '\0') return;

// Perform single-threaded sanitization
for (size_t i = 0; i < sizeof(offensive_words) / sizeof(offensive_words[0]); ++i) {
while (custom_strcasestr(input, offensive_words[i]) != NULL) {
replace_substring_case_insensitive(input, offensive_words[i], "***");
}
for (size_t i = 0; i < sizeof(FOSSIL_SOAP_OFFENSIVE) / sizeof(FOSSIL_SOAP_OFFENSIVE[0]); ++i) {
replace_substring_case_insensitive(input, FOSSIL_SOAP_OFFENSIVE[i], "***");
}

for (size_t i = 0; i < sizeof(FOSSIL_SOAP_ROTBRAIN) / sizeof(FOSSIL_SOAP_ROTBRAIN[0]); ++i) {
replace_substring_case_insensitive(input, FOSSIL_SOAP_ROTBRAIN[i], "***");
}
}

// Function to check if a word is an offensive word or phrase
int32_t fossil_soap_is_offensive(const char *word) {
if (word == NULL || *word == '\0') return EXIT_SUCCESS;

for (size_t i = 0; i < sizeof(offensive_words) / sizeof(offensive_words[0]); ++i) {
if (strcasecmp(word, offensive_words[i]) == 0) {
for (size_t i = 0; i < sizeof(FOSSIL_SOAP_OFFENSIVE) / sizeof(FOSSIL_SOAP_OFFENSIVE[0]); ++i) {
if (strcasecmp(word, FOSSIL_SOAP_OFFENSIVE[i]) == 0) {
return EXIT_FAILURE;
}
}
Expand All @@ -133,15 +149,44 @@ int32_t fossil_soap_count_offensive(const char *input) {
if (input == NULL || *input == '\0') return 0;

int count = 0;
char *copy = _custom_fossil_strdup(input);
char *copy = custom_strdup(input);
if (copy == NULL) return EXIT_SUCCESS;

char *token = strtok(copy, " "); // Tokenize the string by space
char *token = strtok(copy, " ,.!?;:"); // Tokenize the string by space and punctuation
while (token != NULL) {
if (fossil_soap_is_offensive(token)) {
count++;
}
token = strtok(NULL, " ");
token = strtok(NULL, " ,.!?;:");
}
free(copy); // Free the memory allocated for the copy
return count;
}

int32_t fossil_soap_is_rotbrain(const char *word) {
if (word == NULL || *word == '\0') return EXIT_SUCCESS;

for (size_t i = 0; i < sizeof(FOSSIL_SOAP_ROTBRAIN) / sizeof(FOSSIL_SOAP_ROTBRAIN[0]); ++i) {
if (strcasecmp(word, FOSSIL_SOAP_ROTBRAIN[i]) == 0) {
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}

int32_t fossil_soap_count_rotbrain(const char *input) {
if (input == NULL || *input == '\0') return 0;

int count = 0;
char *copy = custom_strdup(input);
if (copy == NULL) return EXIT_SUCCESS;

char *token = strtok(copy, " ,.!?;:"); // Tokenize the string by space and punctuation
while (token != NULL) {
if (fossil_soap_is_rotbrain(token)) {
count++;
}
token = strtok(NULL, " ,.!?;:");
}
free(copy); // Free the memory allocated for the copy
return count;
Expand Down
101 changes: 101 additions & 0 deletions code/tests/cases/test_soap.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,94 @@ FOSSIL_TEST_CASE(c_test_soap_count_offensive) {
ASSUME_ITS_EQUAL_I32(2, fossil_soap_count_offensive(input));
}

FOSSIL_TEST_CASE(c_test_soap_is_rotbrain) {
ASSUME_ITS_TRUE(fossil_soap_is_rotbrain("lol"));
ASSUME_ITS_TRUE(fossil_soap_is_rotbrain("brb"));
ASSUME_ITS_FALSE(fossil_soap_is_rotbrain("hello"));
}

FOSSIL_TEST_CASE(c_test_soap_count_rotbrain) {
char input[] = "This is a test with lol and brb";
ASSUME_ITS_EQUAL_I32(2, fossil_soap_count_rotbrain(input));
}

FOSSIL_TEST_CASE(c_test_soap_sanitize_multiple_offensive) {
char input[] = "curse1 curse2 racist_phrase1 racist_phrase2";
char expected[] = "*** *** *** ***";

fossil_soap_sanitize(input);

ASSUME_ITS_EQUAL_CSTR(expected, input);
}

FOSSIL_TEST_CASE(c_test_soap_sanitize_no_offensive) {
char input[] = "This is a clean sentence.";
char expected[] = "This is a clean sentence.";

fossil_soap_sanitize(input);

ASSUME_ITS_EQUAL_CSTR(expected, input);
}

FOSSIL_TEST_CASE(c_test_soap_is_offensive_case_insensitive) {
ASSUME_ITS_TRUE(fossil_soap_is_offensive("CuRsE1"));
ASSUME_ITS_TRUE(fossil_soap_is_offensive("RaCiSt_PhrAsE2"));
ASSUME_ITS_FALSE(fossil_soap_is_offensive("Non_Offensive_Word"));
}

FOSSIL_TEST_CASE(c_test_soap_count_offensive_mixed_case) {
char input[] = "This is a test with CuRsE1 and RaCiSt_PhrAsE1";
ASSUME_ITS_EQUAL_I32(2, fossil_soap_count_offensive(input));
}

FOSSIL_TEST_CASE(c_test_soap_is_rotbrain_case_insensitive) {
ASSUME_ITS_TRUE(fossil_soap_is_rotbrain("LoL"));
ASSUME_ITS_TRUE(fossil_soap_is_rotbrain("BrB"));
ASSUME_ITS_FALSE(fossil_soap_is_rotbrain("Hello"));
}

FOSSIL_TEST_CASE(c_test_soap_count_rotbrain_mixed_case) {
char input[] = "This is a test with LoL and BrB";
ASSUME_ITS_EQUAL_I32(2, fossil_soap_count_rotbrain(input));
}

FOSSIL_TEST_CASE(c_test_soap_sanitize_synonyms) {
char input[] = "This is a test with rizz and sus.";
char expected[] = "This is a test with *** and ***.";

fossil_soap_sanitize(input);

ASSUME_ITS_EQUAL_CSTR(expected, input);
}

FOSSIL_TEST_CASE(c_test_soap_sanitize_with_punctuation) {
char input[] = "This is a test with curse1, and racist_phrase1!";
char expected[] = "This is a test with ***, and ***!";

fossil_soap_sanitize(input);

ASSUME_ITS_EQUAL_CSTR(expected, input);
}

FOSSIL_TEST_CASE(c_test_soap_count_offensive_with_punctuation) {
char input[] = "This is a test with curse1, and racist_phrase1!";
ASSUME_ITS_EQUAL_I32(2, fossil_soap_count_offensive(input));
}

FOSSIL_TEST_CASE(c_test_soap_sanitize_rotbrain_with_punctuation) {
char input[] = "This is a test with lol, and brb!";
char expected[] = "This is a test with ***, and ***!";

fossil_soap_sanitize(input);

ASSUME_ITS_EQUAL_CSTR(expected, input);
}

FOSSIL_TEST_CASE(c_test_soap_count_rotbrain_with_punctuation) {
char input[] = "This is a test with lol, and brb!";
ASSUME_ITS_EQUAL_I32(2, fossil_soap_count_rotbrain(input));
}

// * * * * * * * * * * * * * * * * * * * * * * * *
// * Fossil Logic Test Pool
// * * * * * * * * * * * * * * * * * * * * * * * *
Expand All @@ -71,6 +159,19 @@ FOSSIL_TEST_GROUP(c_soap_tests) {
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_sanitize);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_is_offensive);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_count_offensive);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_is_rotbrain);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_count_rotbrain);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_sanitize_multiple_offensive);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_sanitize_no_offensive);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_is_offensive_case_insensitive);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_count_offensive_mixed_case);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_is_rotbrain_case_insensitive);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_count_rotbrain_mixed_case);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_sanitize_synonyms);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_sanitize_with_punctuation);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_count_offensive_with_punctuation);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_sanitize_rotbrain_with_punctuation);
FOSSIL_TEST_ADD(c_soap_suite, c_test_soap_count_rotbrain_with_punctuation);

FOSSIL_TEST_REGISTER(c_soap_suite);
}
Loading
Loading