diff --git a/common/say_link.cpp b/common/say_link.cpp index b4824ac48..1e35d8294 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -322,145 +322,54 @@ std::string EQ::SayLinkEngine::GenerateQuestSaylink(std::string saylink_text, bo std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message) { - std::string new_message = message; - int link_index = 0; - int saylink_index = 0; - std::vector links = {}; - std::vector saylinks = {}; - int saylink_length = 50; - std::string saylink_separator = "\u0012"; - std::string saylink_partial = "00000"; + LogSaylinkDetail("message [{}]", message); - LogSaylinkDetail("new_message pre pass 1 [{}]", new_message); + std::string new_message; + new_message.reserve(strlen(message)); - // first pass - strip existing saylinks by putting placeholder anchors on them - for (auto &saylink: Strings::Split(new_message, saylink_separator)) { - if (!saylink.empty() && saylink.length() > saylink_length && - saylink.find(saylink_partial) != std::string::npos) { - saylinks.emplace_back(saylink); + bool in_bracket_state = false; + bool in_link_state = false; - LogSaylinkDetail("Found saylink [{}]", saylink); + const char* ch = message; + const char* startpos = message; + for (; *ch != '\0'; ++ch) + { + // saylinks not added if spaces touch brackets + bool abort_space = in_bracket_state && *ch == ' ' && (*(ch-1) == '[' || *(ch+1) == ']'); - // replace with anchor - Strings::FindReplace( - new_message, - fmt::format("{}", saylink), - fmt::format("", saylink_index) - ); - - saylink_index++; + if (in_bracket_state && (*ch == '[' || *ch == '\x12' || abort_space)) + { + // abort due to nested bracket (which starts another) or existing saylink + new_message.append(startpos, ch - startpos); + in_bracket_state = false; } - } - - LogSaylinkDetail("new_message post pass 1 [{}]", new_message); - - LogSaylinkDetail("saylink separator count [{}]", std::count(new_message.begin(), new_message.end(), '\u0012')); - - // loop through brackets until none exist - if (new_message.find('[') != std::string::npos) { - for (auto &b: Strings::Split(new_message, "[")) { - if (!b.empty() && b.find(']') != std::string::npos) { - std::vector right_split = Strings::Split(b, "]"); - if (!right_split.empty()) { - std::string bracket_message = Strings::Trim(right_split[0]); - - // we shouldn't see a saylink fragment here, ignore this bracket - if (bracket_message.find(saylink_partial) != std::string::npos) { - continue; - } - - // skip where multiple saylinks are within brackets - if (bracket_message.find(saylink_separator) != std::string::npos && - std::count(bracket_message.begin(), bracket_message.end(), '\u0012') > 1) { - continue; - } - - // if non empty bracket contents - if (!bracket_message.empty()) { - LogSaylinkDetail("Found bracket_message [{}]", bracket_message); - - // already a saylink - // todo: improve this later - if (!bracket_message.empty() && - (bracket_message.length() > saylink_length || - bracket_message.find(saylink_separator) != std::string::npos)) { - links.emplace_back(bracket_message); - } - else { - links.emplace_back( - EQ::SayLinkEngine::GenerateQuestSaylink( - bracket_message, - false, - bracket_message - ) - ); - } - - // replace with anchor - Strings::FindReplace( - new_message, - fmt::format("[{}]", bracket_message), - fmt::format("", link_index) - ); - - link_index++; - } - } + else if (in_bracket_state && *ch == ']') + { + if (ch != startpos) + { + std::string str(startpos, ch - startpos); + new_message += EQ::SayLinkEngine::GenerateQuestSaylink(str, false, str); } + in_bracket_state = false; + } + + if (!in_bracket_state) + { + new_message.push_back(*ch); + } + + if (*ch == '[' && !in_link_state) + { + startpos = ch + 1; + in_bracket_state = true; + } + else if (*ch == '\x12') + { + in_link_state = !in_link_state; } } - LogSaylinkDetail("new_message post pass 2 (post brackets) [{}]", new_message); - - // strip any current delimiters of saylinks - Strings::FindReplace(new_message, saylink_separator, ""); - - // pop links onto anchors - link_index = 0; - for (auto &link: links) { - - // strip any current delimiters of saylinks - Strings::FindReplace(link, saylink_separator, ""); - - Strings::FindReplace( - new_message, - fmt::format("", link_index), - fmt::format("[\u0012{}\u0012]", link) - ); - link_index++; - } - - LogSaylinkDetail("new_message post pass 3 (post prelink anchor pop) [{}]", new_message); - - // pop links onto anchors - saylink_index = 0; - for (auto &link: saylinks) { - // strip any current delimiters of saylinks - Strings::FindReplace(link, saylink_separator, ""); - - // check to see if we did a double anchor pass (existing saylink that was also inside brackets) - // this means we found a saylink and we're checking to see if we're already encoded before double encoding - if (new_message.find(fmt::format("\u0012\u0012", saylink_index)) != std::string::npos) { - LogSaylinkDetail("Found encoded saylink at index [{}]", saylink_index); - - Strings::FindReplace( - new_message, - fmt::format("\u0012\u0012", saylink_index), - fmt::format("\u0012{}\u0012", link) - ); - saylink_index++; - continue; - } - - Strings::FindReplace( - new_message, - fmt::format("", saylink_index), - fmt::format("\u0012{}\u0012", link) - ); - saylink_index++; - } - - LogSaylinkDetail("new_message post pass 4 (post saylink anchor pop) [{}]", new_message); + LogSaylinkDetail("new_message [{}]", new_message); return new_message; }