Clean up SearchReplaceEngine a bit

This commit is contained in:
Thomas Goyne 2013-01-13 08:09:11 -08:00
parent f8b717e9ac
commit 6be8d32929

View file

@ -41,26 +41,28 @@ struct MatchState {
}; };
namespace { namespace {
template<typename AssDialogue> auto get_dialogue_field(SearchReplaceSettings::Field field) -> decltype(&AssDialogue::Text) {
auto get_dialogue_field(AssDialogue *cur, SearchReplaceSettings::Field field) -> decltype(&cur->Text) {
switch (field) { switch (field) {
case SearchReplaceSettings::Field::TEXT: return &cur->Text; case SearchReplaceSettings::Field::TEXT: return &AssDialogue::Text;
case SearchReplaceSettings::Field::STYLE: return &cur->Style; case SearchReplaceSettings::Field::STYLE: return &AssDialogue::Style;
case SearchReplaceSettings::Field::ACTOR: return &cur->Actor; case SearchReplaceSettings::Field::ACTOR: return &AssDialogue::Actor;
case SearchReplaceSettings::Field::EFFECT: return &cur->Effect; case SearchReplaceSettings::Field::EFFECT: return &AssDialogue::Effect;
} }
throw agi::InternalError("Bad field for search", 0); throw agi::InternalError("Bad field for search", 0);
} }
typedef std::function<MatchState (const AssDialogue*, size_t)> matcher; typedef std::function<MatchState (const AssDialogue*, size_t)> matcher;
struct noop_accessor { class noop_accessor {
SearchReplaceSettings::Field field; boost::flyweight<wxString> AssDialogue::*field;
size_t start; size_t start;
public:
noop_accessor(SearchReplaceSettings::Field f) : field(get_dialogue_field(f)), start(0) { }
wxString get(const AssDialogue *d, size_t s) { wxString get(const AssDialogue *d, size_t s) {
start = s; start = s;
return get_dialogue_field(d, field)->get().substr(s); return (d->*field).get().substr(s);
} }
MatchState make_match_state(size_t s, size_t e, wxRegEx *r = nullptr) { MatchState make_match_state(size_t s, size_t e, wxRegEx *r = nullptr) {
@ -68,8 +70,8 @@ struct noop_accessor {
} }
}; };
struct skip_tags_accessor { class skip_tags_accessor {
SearchReplaceSettings::Field field; boost::flyweight<wxString> AssDialogue::*field;
std::vector<std::pair<size_t, size_t>> blocks; std::vector<std::pair<size_t, size_t>> blocks;
size_t start; size_t start;
@ -89,8 +91,11 @@ struct skip_tags_accessor {
} }
} }
public:
skip_tags_accessor(SearchReplaceSettings::Field f) : field(get_dialogue_field(f)), start(0) { }
wxString get(const AssDialogue *d, size_t s) { wxString get(const AssDialogue *d, size_t s) {
auto const& str = get_dialogue_field(d, field)->get(); auto const& str = (d->*field).get();
parse_str(str); parse_str(str);
wxString out; wxString out;
@ -181,13 +186,9 @@ matcher get_matcher(SearchReplaceSettings const& settings, wxRegEx *regex, Acces
} }
matcher get_matcher(SearchReplaceSettings const& settings, wxRegEx *regex) { matcher get_matcher(SearchReplaceSettings const& settings, wxRegEx *regex) {
if (!settings.skip_tags) { if (settings.skip_tags)
noop_accessor a = { settings.field }; return get_matcher(settings, regex, skip_tags_accessor(settings.field));
return get_matcher(settings, regex, a); return get_matcher(settings, regex, noop_accessor(settings.field));
}
skip_tags_accessor a = { settings.field };
return get_matcher(settings, regex, a);
} }
template<typename Iterator, typename Container> template<typename Iterator, typename Container>
@ -207,8 +208,8 @@ SearchReplaceEngine::SearchReplaceEngine(agi::Context *c)
} }
void SearchReplaceEngine::Replace(AssDialogue *diag, MatchState &ms) { void SearchReplaceEngine::Replace(AssDialogue *diag, MatchState &ms) {
auto diag_field = get_dialogue_field(diag, settings.field); auto& diag_field = diag->*get_dialogue_field(settings.field);
auto text = diag_field->get(); auto text = diag_field.get();
wxString replacement = settings.replace_with; wxString replacement = settings.replace_with;
if (ms.re) { if (ms.re) {
@ -217,7 +218,7 @@ void SearchReplaceEngine::Replace(AssDialogue *diag, MatchState &ms) {
replacement = to_replace; replacement = to_replace;
} }
*diag_field = text.substr(0, ms.start) + replacement + text.substr(ms.end); diag_field = text.substr(0, ms.start) + replacement + text.substr(ms.end);
ms.end = ms.start + replacement.size(); ms.end = ms.start + replacement.size();
} }
@ -316,13 +317,13 @@ bool SearchReplaceEngine::ReplaceAll() {
if (settings.use_regex) { if (settings.use_regex) {
if (MatchState ms = matches(diag, 0)) { if (MatchState ms = matches(diag, 0)) {
auto diag_field = get_dialogue_field(diag, settings.field); auto& diag_field = diag->*get_dialogue_field(settings.field);
auto text = diag_field->get(); auto text = diag_field.get();
// A zero length match (such as '$') will always be replaced // A zero length match (such as '$') will always be replaced
// maxMatches times, which is almost certainly not what the user // maxMatches times, which is almost certainly not what the user
// wanted, so limit it to one replacement in that situation // wanted, so limit it to one replacement in that situation
count += ms.re->Replace(&text, settings.replace_with, ms.start == ms.end); count += ms.re->Replace(&text, settings.replace_with, ms.start == ms.end);
*diag_field = text; diag_field = text;
} }
continue; continue;
} }