summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonetienne <leonetienne@hotmail.de>2022-03-19 08:33:01 +0100
committerLeonetienne <leonetienne@hotmail.de>2022-03-19 08:47:54 +0100
commit577bc93d6d2fa2645a121c7c454248d8a663a8b6 (patch)
treecb1c5099bdb70ef7f809be7af8550830e594ec07
parentb172ec9ee901d95bdd959665399a87ff033ed9a9 (diff)
Move all uwu-related code to its own header, and create a few dont-crash tests
awso fixed stwing-out-of-range bug.
-rw-r--r--Src/CMakeLists.txt2
-rw-r--r--Src/LibUwu.h239
-rw-r--r--Src/main.cpp236
-rw-r--r--Test/CMakeLists.txt1
-rw-r--r--Test/HappyPath.cpp17
5 files changed, 259 insertions, 236 deletions
diff --git a/Src/CMakeLists.txt b/Src/CMakeLists.txt
index e2a860c..56d48ee 100644
--- a/Src/CMakeLists.txt
+++ b/Src/CMakeLists.txt
@@ -17,7 +17,7 @@ link_directories(Lib/StringTools/Src/cmake-build-release/)
add_executable(Uwwwu
Util.cpp
main.cpp
-)
+ LibUwu.h)
# Link StringTools library
target_link_libraries(Uwwwu StringTools)
diff --git a/Src/LibUwu.h b/Src/LibUwu.h
new file mode 100644
index 0000000..b1e0cf0
--- /dev/null
+++ b/Src/LibUwu.h
@@ -0,0 +1,239 @@
+#ifndef UWWWU_LIBUWU_H
+#define UWWWU_LIBUWU_H
+
+#include <StringTools.h>
+#include <CharTools.h>
+#include <string>
+#include <sstream>
+#include <functional>
+#include <random>
+#include "Util.h"
+
+// This validator will only replace findings, if they are a complete word, and not just part of a word.
+static inline auto ValidatorFindingIsCompleteWord(const std::string& original, const std::string& finding, const std::size_t index) -> bool {
+ // Quick-accept: Original-string length matches finding-string length
+ if (original.length() == finding.length())
+ return true;
+
+ bool lastCharBreaksWord = true; // Default is true, because this value stays in case there is no last/next char.
+ bool nextCharBreaksWord = true; // In this case, "no character" would imply the word to be broken.
+
+ // Assign surrounding chars, if possible
+ if (index > 0)
+ lastCharBreaksWord = !CharTools::IsLetter(original[index - 1]);
+ if (index + finding.length() < original.length())
+ nextCharBreaksWord = !CharTools::IsLetter(original[index + finding.length()]);
+
+ // If both the last and the next character are word-breaking, replace.
+ if (lastCharBreaksWord && nextCharBreaksWord)
+ return true;
+ // Else: don't
+ else
+ return false;
+}
+
+
+//! Will make a boring string look sooper dooper kawaii and cute :3
+static inline std::string MakeUwu(std::string boringString) {
+ // Easy ones first
+ // none, lol
+
+ // Slightly more complex... Multichar replacements, but we have to keep capitalization...
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "th", "tw");
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "ove", "uv");
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "have", "haf");
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "tr", "tw");
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "up", "uwp");
+
+ // Let's do some language adjustments
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "twank you", "you're twe best <3333 xoxo", ValidatorFindingIsCompleteWord);
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "good", "sooper dooper", ValidatorFindingIsCompleteWord);
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "suwper", "sooper dooper", ValidatorFindingIsCompleteWord);
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "well", "sooper dooper", ValidatorFindingIsCompleteWord);
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "emacs", "vim", ValidatorFindingIsCompleteWord);
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "twanks", "you're twe best :33 xoxo", ValidatorFindingIsCompleteWord);
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "hello", "hiiiiiii", ValidatorFindingIsCompleteWord);
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "dear", "hiiiiiii", ValidatorFindingIsCompleteWord);
+
+ // Let's extend some phonetics
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "hi", "hiiiiiii");
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "ay", "aaay");
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "ey", "eeey");
+
+ // Replace N with Ny, but only if succeeded by a vowel, and not (preceded by an o and succeeded by an "e{nonletter}"): "one" has such a niche pronunciation...
+ boringString = Util::ConditionalReplaceButKeepSigns(
+ boringString,
+ "n",
+ "ny",
+ [](const std::string& original, const std::string& finding, const std::size_t index) {
+ // Don't replace, if we are on the last char
+ if (index + finding.length() == original.length())
+ return false;
+
+ const char nextChar = CharTools::MakeLower(original[index + finding.length()]);
+ const bool haveLastchar = index > 0; // Do we even have a last char?
+ const char lastChar = haveLastchar ? CharTools::MakeLower(original[index - 1]) : '\0';
+
+ // Apply the complex "one\b"-rule:
+ // (don't replace if 'n' is preceded by 'o' and succeeded by 'e', which is succeeded by a word break)
+ {
+ bool nextNextCharIsNotLetter = false;
+ char nextNextChar;
+
+ // How much length is left including `nextChar`?
+ const std::size_t sizeLeft = original.length() - (index + finding.length());
+
+ // We have room to pick the nextNext char...
+ if (sizeLeft > 1)
+ {
+ nextNextChar = CharTools::MakeLower(original[index + finding.length() + 1]);
+ nextNextCharIsNotLetter = !CharTools::IsLetter(nextNextChar);
+ }
+
+ const bool nextNextCharBreaksWord = (sizeLeft == 1) || (nextNextCharIsNotLetter);
+
+ // Don't replace if:
+ // (lastChar == o) && (nextChar == e) && (nextNextCharBreaksWord)
+ if ((haveLastchar) && (lastChar == 'o') && (nextChar == 'e') && (nextNextCharBreaksWord))
+ return false;
+ }
+
+ // Is this a vowel?
+ if (CharTools::IsVowel(nextChar))
+ return true;
+
+ // Else, don't replace
+ return false;
+ }
+ );
+
+ // Replace R with W, but only if not succeeded by a non-vowel, and if it's not the first character of a word
+ boringString = Util::ConditionalReplaceButKeepSigns(
+ boringString,
+ "r",
+ "w",
+ [](const std::string& original, const std::string& finding, const std::size_t index) {
+ // Don't replace, if we are on the last char
+ if (index + finding.length() == original.length())
+ return false;
+
+ // Don't replace if we're at index 0
+ if (index == 0)
+ return false;
+
+ const char nextChar = CharTools::MakeLower(original[index + finding.length()]);
+ const char lastChar = CharTools::MakeLower(original[index - 1]);
+
+ // Is this a non-vowel?
+ if (!CharTools::IsVowel(nextChar))
+ return false;
+
+ // Don't replace if the last char is not a letter
+ if (!CharTools::IsLetter(lastChar))
+ return false;
+
+ // Else, replace
+ return true;
+ }
+ );
+
+ // Replace L with W, but only if not followed or preceded by another L, and if it's not the first character of a word
+ boringString = Util::ConditionalReplaceButKeepSigns(
+ boringString,
+ "l",
+ "w",
+ [](const std::string& original, const std::string& finding, const std::size_t index) {
+ // Our segment has to be at least two characters long
+ if (original.length() < finding.length() + 2)
+ return false;
+
+ // Don't replace if we're at index o
+ if (index == 0)
+ return false;
+
+ const char lastChar = CharTools::MakeLower(original[index - 1]);
+ const char nextChar = CharTools::MakeLower(original[index + finding.length()]);
+
+ // Don't replace if the last char is not a letter
+ if (!CharTools::IsLetter(lastChar))
+ return false;
+
+ return (lastChar != 'l') && (nextChar != 'l');
+ }
+ );
+
+ // Replace LL with WW, but only if followed by a vowel
+ boringString = Util::ConditionalReplaceButKeepSigns(
+ boringString,
+ "ll",
+ "ww",
+ [](const std::string& original, const std::string& finding, const std::size_t index) {
+ // Don't replace, if we are on the last char
+ if (index + finding.length() == original.length())
+ return false;
+
+ const char nextChar = CharTools::MakeLower(original[index + finding.length()]);
+
+ return CharTools::IsVowel(nextChar);
+ }
+ );
+
+ // Replace ER with A, but only if it's the last two letters of a word
+ boringString = Util::ConditionalReplaceButKeepSigns(
+ boringString,
+ "er",
+ "a",
+ [](const std::string& original, const std::string& finding, const std::size_t index) {
+ // Replace if we're at the end of this line/segment
+ if (index + finding.length() == original.length())
+ return true;
+
+ // Fetch the next char
+ const char nextChar = CharTools::MakeLower(original[index + finding.length()]);
+
+ // Replace if the next char is not a letter
+ return !CharTools::IsLetter(nextChar);
+ }
+ );
+
+ // Replace random punctuation with uwwwwu cute symbols
+ // About evewy fifteenth symbol
+ std::stringstream ss;
+ std::mt19937 rng(std::hash<std::string>()(boringString)); // Seed rng based on string
+ for (const char c : boringString)
+ {
+ if ((c == '.') && (rng() % 15 == 0))
+ {
+ ss << " <3333 ^.^ ";
+ }
+ else if ((c == '!') && (rng() % 15 == 0))
+ {
+ ss << "!! Thadws impowtant! <3 ";
+ }
+ else if ((c == ',') && (rng() % 15 == 0))
+ {
+ ss << " <3 aaaaaand ";
+ }
+ else if ((c == '?') && (rng() % 15 == 0))
+ {
+ ss << "?? now tell me! >:( ";
+ }
+ else
+ ss << c;
+ }
+ boringString = ss.str();
+
+ // Also replace some ascii-"emojis'
+ boringString = StringTools::Replace(boringString, ":)", "UwU :D");
+ boringString = StringTools::Replace(boringString, ":D", ":3");
+ boringString = StringTools::Replace(boringString, ":-)", "UwwwU :3");
+ boringString = StringTools::Replace(boringString, "^^", "^.^ UwU");
+
+ // Some language replacement should happen after these more complex rules
+ boringString = Util::ConditionalReplaceButKeepSigns(boringString, "c++", "c++ (rust is hella cutewr btw ^^)");
+
+
+ return boringString;
+}
+
+#endif //UWWWU_LIBUWU_H
diff --git a/Src/main.cpp b/Src/main.cpp
index 26e9fdb..1f23047 100644
--- a/Src/main.cpp
+++ b/Src/main.cpp
@@ -1,239 +1,5 @@
#include <iostream>
-#include <StringTools.h>
-#include <CharTools.h>
-#include <string>
-#include <sstream>
-#include <functional>
-#include <random>
-#include "Util.h"
-
-// This validator will only replace findings, if they are a complete word, and not just part of a word.
-auto ValidatorFindingIsCompleteWord(const std::string& original, const std::string& finding, const std::size_t index) -> bool {
- // Quick-accept: Original-string length matches finding-string length
- if (original.length() == finding.length())
- return true;
-
- bool lastCharBreaksWord = true; // Default is true, because this value stays in case there is no last/next char.
- bool nextCharBreaksWord = true; // In this case, "no character" would imply the word to be broken.
-
- // Assign surrounding chars, if possible
- if (index > 0)
- lastCharBreaksWord = !CharTools::IsLetter(original[index - 1]);
- if (index + finding.length() < original.length())
- nextCharBreaksWord = !CharTools::IsLetter(original[index + finding.length()]);
-
- // If both the last and the next character are word-breaking, replace.
- if (lastCharBreaksWord && nextCharBreaksWord)
- return true;
- // Else: don't
- else
- return false;
-}
-
-
-//! Will make a boring string look sooper dooper kawaii and cute :3
-std::string MakeUwu(std::string boringString) {
- // Easy ones first
- // none, lol
-
- // Slightly more complex... Multichar replacements, but we have to keep capitalization...
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "th", "tw");
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "ove", "uv");
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "have", "haf");
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "tr", "tw");
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "up", "uwp");
-
- // Let's do some language adjustments
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "twank you", "you're twe best <3333 xoxo", ValidatorFindingIsCompleteWord);
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "good", "sooper dooper", ValidatorFindingIsCompleteWord);
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "suwper", "sooper dooper", ValidatorFindingIsCompleteWord);
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "well", "sooper dooper", ValidatorFindingIsCompleteWord);
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "emacs", "vim", ValidatorFindingIsCompleteWord);
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "twanks", "you're twe best :33 xoxo", ValidatorFindingIsCompleteWord);
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "hello", "hiiiiiii", ValidatorFindingIsCompleteWord);
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "dear", "hiiiiiii", ValidatorFindingIsCompleteWord);
-
- // Let's extend some phonetics
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "hi", "hiiiiiii");
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "ay", "aaay");
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "ey", "eeey");
-
- // Replace N with Ny, but only if succeeded by a vowel, and not (preceded by an o and succeeded by an "e{nonletter}"): "one" has such a niche pronunciation...
- boringString = Util::ConditionalReplaceButKeepSigns(
- boringString,
- "n",
- "ny",
- [](const std::string& original, const std::string& finding, const std::size_t index) {
- // Jävla this is one clustered piece of shitcode
-
- // Don't replace, if we are on the last char
- if (index + finding.length() == original.length())
- return false;
-
- const char nextChar = CharTools::MakeLower(original[index + finding.length()]);
- const char lastChar = CharTools::MakeLower(original[index - 1]);
-
- // Apply the complex "one\b"-rule:
- // (don't replace if 'n' is preceded by 'o' and succeeded by 'e', which is succeeded by a word break)
- {
- bool nextNextCharIsNotLetter = false;
- char nextNextChar;
-
- // How much length is left including `nextChar`?
- const std::size_t sizeLeft = original.length() - (index + finding.length());
-
- // We have room to pick the nextNext char...
- if (sizeLeft > 1)
- {
- nextNextChar = CharTools::MakeLower(original[index + finding.length() + 1]);
- nextNextCharIsNotLetter = !CharTools::IsLetter(nextNextChar);
- }
-
- const bool nextNextCharBreaksWord = (sizeLeft == 1) || (nextNextCharIsNotLetter);
-
- // Don't replace if:
- // (lastChar == o) && (nextChar == e) && (nextNextCharBreaksWord)
- if ((lastChar == 'o') && (nextChar == 'e') && (nextNextCharBreaksWord))
- return false;
- }
-
- // Is this a vowel?
- if (CharTools::IsVowel(nextChar))
- return true;
-
- // Else, don't replace
- return false;
- }
- );
-
- // Replace R with W, but only if not succeeded by a non-vowel, and if it's not the first character of a word
- boringString = Util::ConditionalReplaceButKeepSigns(
- boringString,
- "r",
- "w",
- [](const std::string& original, const std::string& finding, const std::size_t index) {
- // Don't replace, if we are on the last char
- if (index + finding.length() == original.length())
- return false;
-
- // Don't replace if we're at index 0
- if (index == 0)
- return false;
-
- const char nextChar = CharTools::MakeLower(original[index + finding.length()]);
- const char lastChar = CharTools::MakeLower(original[index - 1]);
-
- // Is this a non-vowel?
- if (!CharTools::IsVowel(nextChar))
- return false;
-
- // Don't replace if the last char is not a letter
- if (!CharTools::IsLetter(lastChar))
- return false;
-
- // Else, replace
- return true;
- }
- );
-
- // Replace L with W, but only if not followed or preceded by another L, and if it's not the first character of a word
- boringString = Util::ConditionalReplaceButKeepSigns(
- boringString,
- "l",
- "w",
- [](const std::string& original, const std::string& finding, const std::size_t index) {
- // Our segment has to be at least two characters long
- if (original.length() < finding.length() + 2)
- return false;
-
- // Don't replace if we're at index o
- if (index == 0)
- return false;
-
- const char lastChar = CharTools::MakeLower(original[index - 1]);
- const char nextChar = CharTools::MakeLower(original[index + finding.length()]);
-
- // Don't replace if the last char is not a letter
- if (!CharTools::IsLetter(lastChar))
- return false;
-
- return (lastChar != 'l') && (nextChar != 'l');
- }
- );
-
- // Replace LL with WW, but only if followed by a vowel
- boringString = Util::ConditionalReplaceButKeepSigns(
- boringString,
- "ll",
- "ww",
- [](const std::string& original, const std::string& finding, const std::size_t index) {
- // Don't replace, if we are on the last char
- if (index + finding.length() == original.length())
- return false;
-
- const char nextChar = CharTools::MakeLower(original[index + finding.length()]);
-
- return CharTools::IsVowel(nextChar);
- }
- );
-
- // Replace ER with A, but only if it's the last two letters of a word
- boringString = Util::ConditionalReplaceButKeepSigns(
- boringString,
- "er",
- "a",
- [](const std::string& original, const std::string& finding, const std::size_t index) {
- // Replace if we're at the end of this line/segment
- if (index + finding.length() == original.length())
- return true;
-
- // Fetch the next char
- const char nextChar = CharTools::MakeLower(original[index + finding.length()]);
-
- // Replace if the next char is not a letter
- return !CharTools::IsLetter(nextChar);
- }
- );
-
- // Replace random punctuation with uwwwwu cute symbols
- // About evewy fifteenth symbol
- std::stringstream ss;
- std::mt19937 rng(std::hash<std::string>()(boringString)); // Seed rng based on string
- for (const char c : boringString)
- {
- if ((c == '.') && (rng() % 15 == 0))
- {
- ss << " <3333 ^.^ ";
- }
- else if ((c == '!') && (rng() % 15 == 0))
- {
- ss << "!! Thadws impowtant! <3 ";
- }
- else if ((c == ',') && (rng() % 15 == 0))
- {
- ss << " <3 aaaaaand ";
- }
- else if ((c == '?') && (rng() % 15 == 0))
- {
- ss << "?? now tell me! >:( ";
- }
- else
- ss << c;
- }
- boringString = ss.str();
-
- // Also replace some ascii-"emojis'
- boringString = StringTools::Replace(boringString, ":)", "UwU :D");
- boringString = StringTools::Replace(boringString, ":D", ":3");
- boringString = StringTools::Replace(boringString, ":-)", "UwwwU :3");
- boringString = StringTools::Replace(boringString, "^^", "^.^ UwU");
-
- // Some language replacement should happen after these more complex rules
- boringString = Util::ConditionalReplaceButKeepSigns(boringString, "c++", "c++ (rust is hella cutewr btw ^^)");
-
-
- return boringString;
-}
+#include "LibUwu.h"
int main(int argc, char** argv) {
diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt
index c8d4f67..afdd2c6 100644
--- a/Test/CMakeLists.txt
+++ b/Test/CMakeLists.txt
@@ -20,6 +20,7 @@ add_executable(Test
# Uwwwu-Tests
ConditionalReplaceButKeepSigns.cpp
+ HappyPath.cpp
)
target_link_libraries(Test StringTools)
diff --git a/Test/HappyPath.cpp b/Test/HappyPath.cpp
new file mode 100644
index 0000000..7ed31f0
--- /dev/null
+++ b/Test/HappyPath.cpp
@@ -0,0 +1,17 @@
+#include <LibUwu.h>
+#include "Catch2.h"
+
+// Tests that the program doesnt crash with random input
+TEST_CASE(__FILE__"/DoesntCrash", "[]")
+{
+ SECTION("0") { MakeUwu("nine"); }
+ SECTION("1") { MakeUwu("nintendo"); }
+ SECTION("2") { MakeUwu("one"); }
+ SECTION("3") { MakeUwu("rally"); }
+ SECTION("4") { MakeUwu("lary"); }
+ SECTION("5") { MakeUwu("larry"); }
+ SECTION("6") { MakeUwu("wally"); }
+ SECTION("7") { MakeUwu("waly"); }
+ SECTION("8") { MakeUwu("gardener"); }
+ SECTION("9") { MakeUwu("german"); }
+}