mirror of https://github.com/odrling/Aegisub
Extract some more find/replace logic to libaegisub
This commit is contained in:
parent
cad8c80aab
commit
74ac2ab1fe
|
@ -52,8 +52,24 @@ std::pair<size_t, size_t> find_range(std::string const& haystack, std::string co
|
|||
return {match_start, match_start + needle.size()};
|
||||
}
|
||||
|
||||
void parse_blocks(std::vector<std::pair<size_t, size_t>>& blocks, std::string const& str) {
|
||||
blocks.clear();
|
||||
|
||||
size_t ovr_start = bad_pos;
|
||||
size_t i = 0;
|
||||
for (auto const& c : str) {
|
||||
if (c == '{' && ovr_start == bad_pos)
|
||||
ovr_start = i;
|
||||
else if (c == '}' && ovr_start != bad_pos) {
|
||||
blocks.emplace_back(ovr_start, i);
|
||||
ovr_start = bad_pos;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace agi { namespace util {
|
||||
|
||||
std::string strftime(const char *fmt, const tm *tmptr) {
|
||||
|
@ -129,12 +145,60 @@ std::pair<size_t, size_t> ifind(std::string const& haystack, std::string const&
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string tagless_find_helper::strip_tags(std::string const& str, size_t s) {
|
||||
parse_blocks(blocks, str);
|
||||
|
||||
std::string out;
|
||||
|
||||
size_t last = s;
|
||||
for (auto const& block : blocks) {
|
||||
if (block.second < s) continue;
|
||||
if (block.first > last)
|
||||
out.append(str.begin() + last, str.begin() + block.first);
|
||||
last = block.second + 1;
|
||||
}
|
||||
|
||||
if (last < str.size())
|
||||
out.append(str.begin() + last, str.end());
|
||||
|
||||
start = s;
|
||||
return out;
|
||||
}
|
||||
|
||||
void tagless_find_helper::map_range(size_t &s, size_t &e) {
|
||||
s += start;
|
||||
e += start;
|
||||
|
||||
// Shift the start and end of the match to be relative to the unstripped
|
||||
// match
|
||||
for (auto const& block : blocks) {
|
||||
// Any blocks before start are irrelevant as they're included in `start`
|
||||
if (block.second < s) continue;
|
||||
// Skip over blocks at the very beginning of the match
|
||||
// < should only happen if the cursor was within an override block
|
||||
// when the user started a search
|
||||
if (block.first <= s) {
|
||||
size_t len = block.second - std::max(block.first, s) + 1;
|
||||
s += len;
|
||||
e += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(block.first > s);
|
||||
// Blocks after the match are irrelevant
|
||||
if (block.first >= e) break;
|
||||
|
||||
// Extend the match to include blocks within the match
|
||||
// Note that blocks cannot be partially within the match
|
||||
e += block.second - block.first + 1;
|
||||
}
|
||||
}
|
||||
} // namespace util
|
||||
|
||||
#ifndef __APPLE__
|
||||
namespace osx {
|
||||
AppNapDisabler::AppNapDisabler(std::string reason) { }
|
||||
AppNapDisabler::~AppNapDisabler() { }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace agi
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
#include <algorithm>
|
||||
#include <boost/range/irange.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct tm;
|
||||
|
||||
namespace agi {
|
||||
namespace util {
|
||||
namespace agi { namespace util {
|
||||
/// Clamp `b` to the range [`a`,`c`]
|
||||
template<typename T>
|
||||
static inline T mid(T a, T b, T c) {
|
||||
|
@ -45,6 +45,20 @@ namespace agi {
|
|||
/// based on the unfolded length.
|
||||
std::pair<size_t, size_t> ifind(std::string const& haystack, std::string const& needle);
|
||||
|
||||
class tagless_find_helper {
|
||||
std::vector<std::pair<size_t, size_t>> blocks;
|
||||
size_t start = 0;
|
||||
|
||||
public:
|
||||
/// Strip ASS override tags at or after `start` in `str`, and initialize
|
||||
/// state for mapping ranges back to the input string
|
||||
std::string strip_tags(std::string const& str, size_t start);
|
||||
|
||||
/// Convert a range in the string returned by `strip_tags()` to a range
|
||||
/// int the string last passed to `strip_tags()`
|
||||
void map_range(size_t& start, size_t& end);
|
||||
};
|
||||
|
||||
/// Set the name of the calling thread in the Visual Studio debugger
|
||||
/// @param name New name for the thread
|
||||
void SetThreadName(const char *name);
|
||||
|
@ -66,6 +80,4 @@ namespace agi {
|
|||
auto range(Integer end) -> decltype(boost::irange<Integer>(0, end)) {
|
||||
return boost::irange<Integer>(0, end);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace agi
|
||||
} } // namespace agi::util
|
||||
|
|
|
@ -73,76 +73,17 @@ public:
|
|||
|
||||
class skip_tags_accessor {
|
||||
boost::flyweight<std::string> AssDialogueBase::*field;
|
||||
std::vector<std::pair<size_t, size_t>> blocks;
|
||||
size_t start = 0;
|
||||
|
||||
void parse_str(std::string const& str) {
|
||||
blocks.clear();
|
||||
|
||||
size_t ovr_start = bad_pos;
|
||||
size_t i = 0;
|
||||
for (auto const& c : str) {
|
||||
if (c == '{' && ovr_start == bad_pos)
|
||||
ovr_start = i;
|
||||
else if (c == '}' && ovr_start != bad_pos) {
|
||||
blocks.emplace_back(ovr_start, i);
|
||||
ovr_start = bad_pos;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
agi::util::tagless_find_helper helper;
|
||||
|
||||
public:
|
||||
skip_tags_accessor(SearchReplaceSettings::Field f) : field(get_dialogue_field(f)) { }
|
||||
|
||||
std::string get(const AssDialogue *d, size_t s) {
|
||||
auto const& str = get_normalized(d, field);
|
||||
parse_str(str);
|
||||
|
||||
std::string out;
|
||||
|
||||
size_t last = s;
|
||||
for (auto const& block : blocks) {
|
||||
if (block.second < s) continue;
|
||||
if (block.first > last)
|
||||
out.append(str.begin() + last, str.begin() + block.first);
|
||||
last = block.second + 1;
|
||||
}
|
||||
|
||||
if (last < str.size())
|
||||
out.append(str.begin() + last, str.end());
|
||||
|
||||
start = s;
|
||||
return out;
|
||||
return helper.strip_tags(get_normalized(d, field), s);
|
||||
}
|
||||
|
||||
MatchState make_match_state(size_t s, size_t e, boost::u32regex *r = nullptr) {
|
||||
s += start;
|
||||
e += start;
|
||||
|
||||
// Shift the start and end of the match to be relative to the unstripped
|
||||
// match
|
||||
for (auto const& block : blocks) {
|
||||
// Any blocks before start are irrelevant as they're included in `start`
|
||||
if (block.second < s) continue;
|
||||
// Skip over blocks at the very beginning of the match
|
||||
// < should only happen if the cursor was within an override block
|
||||
// when the user started a search
|
||||
if (block.first <= s) {
|
||||
size_t len = block.second - std::max(block.first, s) + 1;
|
||||
s += len;
|
||||
e += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(block.first > s);
|
||||
// Blocks after the match are irrelevant
|
||||
if (block.first >= e) break;
|
||||
|
||||
// Extend the match to include blocks within the match
|
||||
// Note that blocks cannot be partially within the match
|
||||
e += block.second - block.first + 1;
|
||||
}
|
||||
helper.map_range(s, e);
|
||||
return {r, s, e};
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue