Skip to content

Commit

Permalink
String Var: Handle edge cases
Browse files Browse the repository at this point in the history
Support left-adjust for PrependMin
Support indexing from the back with negative values

Fix EasyRPG#3305
  • Loading branch information
Ghabry committed Nov 25, 2024
1 parent 0697a61 commit 713db9d
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 5 deletions.
39 changes: 35 additions & 4 deletions src/game_strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,8 @@ StringView Game_Strings::ExMatch(Str_Params params, std::string expr, int var_id
expr = Extract(expr, params.hex);
}

std::string base = Substring(Get(params.string_id), begin);
auto source = Get(params.string_id);
std::string base = Substring(source, begin, Utils::UTF8Length(source));

std::wsmatch match;
auto wbase = Utils::ToWideString(base);
Expand Down Expand Up @@ -356,7 +357,15 @@ const Game_Strings::Strings_t& Game_Strings::RangeOp(Str_Params params, int stri
std::string Game_Strings::PrependMin(StringView string, int min_size, char c) {
int len = Utils::UTF8Length(string);

if (len < min_size) {
if (min_size < 0) {
// Left adjust
min_size = abs(min_size);
if (len < min_size) {
int s = min_size - len;
return ToString(string) + std::string(s, c);
}
} else if (len < min_size) {
// Right adjust
int s = min_size - len;
return std::string(s, c) + ToString(string);
}
Expand All @@ -379,8 +388,10 @@ std::string Game_Strings::Substring(StringView source, int begin, int length) {
const char* iter = source.data();
const auto end = source.data() + source.size();

if (length == -1) {
length = Utils::UTF8Length(source) - begin;
begin = AdjustIndex(source, begin);

if (length < 0) {
length = 0;
}

// Points at start of the substring
Expand All @@ -400,6 +411,8 @@ std::string Game_Strings::Insert(StringView source, StringView what, int where)
const char* iter = source.data();
const auto end = source.data() + source.size();

where = AdjustIndex(source, where);

// Points at insertion location
auto ret = Utils::UTF8Skip(iter, end, where);

Expand All @@ -410,9 +423,19 @@ std::string Game_Strings::Erase(StringView source, int begin, int length) {
const char* iter = source.data();
const auto end = source.data() + source.size();

begin = AdjustIndex(source, begin);

if (length < 0) {
length = 0;
}

// Points at start of deletion
auto left = Utils::UTF8Skip(iter, end, begin);

if (left.next == nullptr) {
return ToString(source);
}

// Points at end of deletion
auto right = Utils::UTF8Skip(left.next, end, length);

Expand All @@ -438,6 +461,14 @@ std::string Game_Strings::RegExReplace(StringView str, StringView search, String
return Utils::FromWideString(result);
}

int Game_Strings::AdjustIndex(StringView str, int index) {
if (index >= 0) {
return index;
}

return std::max(Utils::UTF8Length(str) - abs(index), 0);
}

std::optional<std::string> Game_Strings::ManiacsCommandInserter(char ch, const char** iter, const char* end, uint32_t escape_char) {
if (ch == 'S' || ch == 's') {
// \s in a normal message is the speed modifier
Expand Down
3 changes: 2 additions & 1 deletion src/game_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,11 @@ class Game_Strings {

static std::string PrependMin(StringView string, int min_size, char c);
static std::string Extract(StringView string, bool as_hex);
static std::string Substring(StringView source, int begin, int length = -1);
static std::string Substring(StringView source, int begin, int length);
static std::string Insert(StringView source, StringView what, int where);
static std::string Erase(StringView source, int begin, int length);
static std::string RegExReplace(StringView str, StringView search, StringView replace, std::regex_constants::match_flag_type flags = std::regex_constants::match_default);
static int AdjustIndex(StringView str, int index);

static std::optional<std::string> ManiacsCommandInserter(char ch, const char** iter, const char* end, uint32_t escape_char);
static std::optional<std::string> ManiacsCommandInserterHex(char ch, const char** iter, const char* end, uint32_t escape_char);
Expand Down
4 changes: 4 additions & 0 deletions src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,10 @@ uint32_t Utils::CRC32(std::istream& stream) {

// via https://stackoverflow.com/q/3418231/
std::string Utils::ReplaceAll(std::string str, const std::string& search, const std::string& replace) {
if (search.empty()) {
return str;
}

size_t start_pos = 0;
while((start_pos = str.find(search, start_pos)) != std::string::npos) {
str.replace(start_pos, search.length(), replace);
Expand Down

0 comments on commit 713db9d

Please sign in to comment.