Skip to content

Commit

Permalink
Make ReplaceInStrings more user friendly
Browse files Browse the repository at this point in the history
  • Loading branch information
maxmitti committed Aug 15, 2024
1 parent 69a457e commit a2caba9
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/C4PlayerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1669,15 +1669,15 @@ bool C4PlayerInfoList::SetAsRestoreInfos(C4PlayerInfoList &rFromPlayers, bool fS

// O(n) is fast.
// If not, blame whoever wrote Replace! ;)
newName = ReplaceInString(std::string_view{newName}, std::string_view{"%"}, std::string_view{"%25"});
newName = ReplaceInString(newName, "%", "%25");
for (int ch = 128; ch < 256; ++ch)
{
const char *hexChars = "0123456789abcdef";
char old[] = { static_cast<char>(ch), 0 };
char safe[] = { '%', 'x', 'x', 0 };
safe[1] = hexChars[ch / 16];
safe[2] = hexChars[ch % 16];
newName = ReplaceInString(std::string_view{newName}, std::string_view{old}, std::string_view{safe});
newName = ReplaceInString(newName, old, safe);
}

pInfo->SetFilename(newName.c_str());
Expand Down
26 changes: 18 additions & 8 deletions src/C4Strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "C4Breakpoint.h"

#include <concepts>
#include <cstddef>
#include <cstdio>
#include <format>
Expand Down Expand Up @@ -103,29 +104,38 @@ int SLineGetCharacters(const char *szText, const char *cpPosition);
// can match strings like "*Cl?nk*vour" to "Clonk Endeavour"
bool SWildcardMatchEx(const char *szString, const char *szWildcard);

template<typename Char, typename Traits>
std::basic_string<Char, Traits> ReplaceInString(std::basic_string_view<Char, Traits> string, std::basic_string_view<Char, Traits> needle, std::basic_string_view<Char, Traits> value)
template <typename T>
concept StringViewable = requires (T t) { std::basic_string_view{t}; };

template <StringViewable T>
using StringViewOf = decltype(std::basic_string_view{std::declval<T>()});

template <StringViewable T>
using StringOf = std::basic_string<typename StringViewOf<T>::value_type, typename StringViewOf<T>::traits_type>;

template<StringViewable Subject, typename View = StringViewOf<Subject>, typename String = StringOf<Subject>>
String ReplaceInString(Subject&& subject, View needle, View value)
{
std::basic_string<Char, Traits> result;
String result;
std::size_t previousPos{0};
std::size_t pos{0};

for (;;)
{
previousPos = pos;
pos = string.find(needle, pos);
if (pos == decltype(string)::npos)
pos = subject.find(needle, pos);
if (pos == String::npos)
{
result.append(string, previousPos);
result.append(subject, previousPos);
return result;
}

result.append(string, previousPos, pos - previousPos);
result.append(subject, previousPos, pos - previousPos);
result.append(value);
pos += value.size();
}

result.append(string, previousPos, string.size() - previousPos);
result.append(subject, previousPos, subject.size() - previousPos);
return result;
}

Expand Down

0 comments on commit a2caba9

Please sign in to comment.