yum-mirror/UwwwuPP

A rehost of leonetienne's UwwwuPP, a simple text filter to uwu-ify English text.

git clone https://git.yummers.dev/yum-mirror/UwwwuPP

LeonetienneLanguage-adjustments nyow onwy affect compwete worwds. Nyice and tested <3333 ^.^b172ec9

master
4.1 KiB112 linesraw
1#include "Util.h"
2#include <CharTools.h>
3#include <StringTools.h>
4#include <sstream>
5
6std::string Util::ConditionalReplaceButKeepSigns(
7        const std::string& str,
8        std::string find,
9        const std::string& sub,
10        const std::function<bool(const std::string&, const std::string&, const std::size_t)>& onlyIf
11)
12{
13
14    // Quick accepts-and rejects
15    if (str.length() == 0)
16        return "";
17    else if (find.length() == 0)
18        return str;
19
20    std::stringstream ss;
21
22    // Better safe than sorry
23    find = StringTools::Lower(find);
24
25    for (std::size_t i = 0; i < str.length(); i++)
26    {
27        const std::string foundInText = str.substr(i, find.length());
28        const std::string foundInText_lower = StringTools::Lower(foundInText);
29        if (foundInText_lower == find)
30        {
31            // Ask the callback if we should replace this one
32            if (onlyIf(str, foundInText, i))
33            {
34                // Here we've found our occurrence...
35                // We have three possible cases:
36                // 1: len(find) == len(sub), in this case we want to sync capitalization by index.
37                // 2: len(find) < len(sub), in this case we sync by index, BUT...
38                // 3: len(find) > len(sub): sync capitalization by index
39
40                // We want to sync capitalization by index
41                // This accounts for both cases: 1 and 3
42                if (foundInText.length() >= sub.length())
43                {
44                    for (std::size_t j = 0; j < sub.length(); j++)
45                    {
46                        const char cf = foundInText[j];
47                        const char cs = sub[j];
48
49                        ss << CharTools::CopySign(cf, cs);
50                    }
51                }
52
53                    // in this case we sync by index, BUT...
54                else if (foundInText.length() < sub.length())
55                {
56                    char followingCharsSign = 0;
57                    bool doHaveFollowingChar = false;
58                    // Do we even have a following char?
59                    if (str.length() >= i + foundInText.length() + 1)
60                    {
61                        const char followingChar = str[i + foundInText.length()];
62
63                        // Is it a letter?
64                        if (CharTools::IsLetter(followingChar))
65                        {
66                            // Copy its sign
67                            followingCharsSign = followingChar;
68                            doHaveFollowingChar = true;
69                        }
70                    }
71
72
73                    char lastCharCharSign = 0;
74                    for (std::size_t j = 0; j < sub.length(); j++)
75                    {
76                        const char cs = sub[j];
77
78                        // Do we still have chars of 'find' left?
79                        if (j < foundInText.length())
80                        {
81                            // Yes: Just copy the sign as is, and update the last sign seen
82                            const char cf = foundInText[j];
83                            lastCharCharSign = cf;
84                            ss << CharTools::CopySign(cf, cs);
85                        }
86                        else
87                        {
88                            // No: Use the last sign seen, or the sign of the following char (the following char within the same word-boundary) (Important for replacing vocals within a word)
89                            const char charSignToUse = doHaveFollowingChar ? followingCharsSign : lastCharCharSign;
90                            ss << CharTools::CopySign(charSignToUse, cs);
91                        }
92                    }
93                }
94            }
95            else
96            {
97                // We do not have an occurrence... just insert the subsection found as is (next iteration will start behind it)
98                ss << foundInText;
99            }
100
101            // Advance i accordingly
102            i += foundInText.length()-1;
103        }
104        else
105        {
106            // We do not have an occurrence... just insert the char as is
107            ss << str[i];
108        }
109    }
110
111    return ss.str();
112}