Skip to content

Commit e7e59e0

Browse files
committed
fix(script_translator): excluded words cause crashes
1 parent de4700e commit e7e59e0

File tree

2 files changed

+88
-77
lines changed

2 files changed

+88
-77
lines changed

src/rime/dict/dictionary.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ bool DictEntryIterator::Next() {
197197
return false;
198198
}
199199
} while (filter_ && !filter_(Peek()));
200-
return true;
200+
return entry_.get();
201201
}
202202

203203
// Note: does not apply filters

src/rime/gear/script_translator.cc

Lines changed: 87 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -569,82 +569,93 @@ inline static bool prefer_user_phrase(
569569
}
570570

571571
bool ScriptTranslation::PrepareCandidate() {
572-
if (exhausted()) {
573-
candidate_source_ = kUninitialized;
574-
candidate_ = nullptr;
575-
return false;
576-
}
577-
if (sentence_) {
578-
candidate_source_ = kSentence;
579-
candidate_ = sentence_;
580-
return true;
581-
}
582-
const size_t full_code_length = end_of_input_ - start_;
583-
size_t user_phrase_code_length = 0;
584-
if (user_phrase_ && user_phrase_iter_ != user_phrase_->rend()) {
585-
user_phrase_code_length = user_phrase_iter_->first;
586-
}
587-
size_t phrase_code_length = 0;
588-
if (phrase_ && phrase_iter_ != phrase_->rend()) {
589-
phrase_code_length = phrase_iter_->first;
590-
}
591-
if (user_phrase_code_length > 0 &&
592-
prefer_user_phrase(
593-
user_phrase_code_length, phrase_code_length,
594-
// 編碼長度相同時, 用戶詞優先
595-
[this, full_code_length, phrase_code_length]() {
596-
UserDictEntryIterator& uter = user_phrase_iter_->second;
597-
DictEntryIterator& iter = phrase_iter_->second;
598-
// 但若用戶詞爲糾錯結果, 則免去優先權, 回歸權重比較
599-
bool user_is_correction = syllabifier_->IsCorrection(
600-
uter.Peek()->code, phrase_code_length);
601-
if (user_is_correction) {
602-
// 因對糾錯候選施加了較大懲罰, 通常結果爲 系統原文 > 用戶糾錯
603-
// 兩者皆糾錯時, 用戶詞的動態權重有助達成 用戶糾錯 > 系統糾錯
604-
return uter.Peek()->weight >= iter.Peek()->weight;
605-
}
606-
// 長詞聯想之前須至少出一個嚴格匹配的候選
607-
// 故確定首選之際, 系統嚴格匹配 > 用戶長詞聯想
608-
const int kNumExactMatchOnTop = 1;
609-
return candidate_index_ >= kNumExactMatchOnTop ||
610-
prefer_user_phrase(
611-
has_exact_match_phrase(user_phrase_, user_phrase_iter_,
612-
full_code_length),
613-
has_exact_match_phrase(phrase_, phrase_iter_,
614-
full_code_length));
615-
})) {
616-
UserDictEntryIterator& uter = user_phrase_iter_->second;
617-
const auto& entry = uter.Peek();
618-
DLOG(INFO) << "user phrase '" << entry->text
619-
<< "', code length: " << user_phrase_code_length;
620-
candidate_source_ = kUserPhrase;
621-
candidate_ =
622-
New<Phrase>(translator_->language(),
623-
entry->IsPredictiveMatch() ? "completion" : "user_phrase",
624-
start_, start_ + user_phrase_code_length, entry);
625-
candidate_->set_quality(std::exp(entry->weight) +
626-
translator_->initial_quality() +
627-
(entry->quality_len / full_code_length));
628-
return true;
629-
} else if (phrase_code_length > 0) {
630-
DictEntryIterator& iter = phrase_iter_->second;
631-
const auto& entry = iter.Peek();
632-
DLOG(INFO) << "phrase '" << entry->text
633-
<< "', code length: " << phrase_code_length;
634-
candidate_source_ = kSysPhrase;
635-
candidate_ =
636-
New<Phrase>(translator_->language(),
637-
entry->IsPredictiveMatch() ? "completion" : "phrase",
638-
start_, start_ + phrase_code_length, entry);
639-
candidate_->set_quality(std::exp(entry->weight) +
640-
translator_->initial_quality() +
641-
(entry->quality_len / full_code_length));
642-
return true;
643-
} else {
644-
candidate_source_ = kUninitialized;
645-
candidate_ = nullptr;
646-
return false;
647-
}
572+
do {
573+
if (exhausted()) {
574+
candidate_source_ = kUninitialized;
575+
candidate_ = nullptr;
576+
return false;
577+
}
578+
if (sentence_) {
579+
candidate_source_ = kSentence;
580+
candidate_ = sentence_;
581+
return true;
582+
}
583+
const size_t full_code_length = end_of_input_ - start_;
584+
size_t user_phrase_code_length = 0;
585+
if (user_phrase_ && user_phrase_iter_ != user_phrase_->rend()) {
586+
user_phrase_code_length = user_phrase_iter_->first;
587+
}
588+
size_t phrase_code_length = 0;
589+
if (phrase_ && phrase_iter_ != phrase_->rend()) {
590+
phrase_code_length = phrase_iter_->first;
591+
}
592+
if (user_phrase_code_length > 0 &&
593+
prefer_user_phrase(
594+
user_phrase_code_length, phrase_code_length,
595+
// 編碼長度相同時, 用戶詞優先
596+
[this, full_code_length, phrase_code_length]() {
597+
UserDictEntryIterator& uter = user_phrase_iter_->second;
598+
DictEntryIterator& iter = phrase_iter_->second;
599+
// 但若用戶詞爲糾錯結果, 則免去優先權, 回歸權重比較
600+
bool user_is_correction = syllabifier_->IsCorrection(
601+
uter.Peek()->code, phrase_code_length);
602+
if (user_is_correction) {
603+
// 因對糾錯候選施加了較大懲罰, 通常結果爲 系統原文 > 用戶糾錯
604+
// 兩者皆糾錯時, 用戶詞的動態權重有助達成 用戶糾錯 > 系統糾錯
605+
return uter.Peek()->weight >= iter.Peek()->weight;
606+
}
607+
// 長詞聯想之前須至少出一個嚴格匹配的候選
608+
// 故確定首選之際, 系統嚴格匹配 > 用戶長詞聯想
609+
const int kNumExactMatchOnTop = 1;
610+
return candidate_index_ >= kNumExactMatchOnTop ||
611+
prefer_user_phrase(
612+
has_exact_match_phrase(user_phrase_, user_phrase_iter_,
613+
full_code_length),
614+
has_exact_match_phrase(phrase_, phrase_iter_,
615+
full_code_length));
616+
})) {
617+
UserDictEntryIterator& uter = user_phrase_iter_->second;
618+
const auto& entry = uter.Peek();
619+
if (!entry) {
620+
++user_phrase_iter_;
621+
continue;
622+
}
623+
DLOG(INFO) << "user phrase '" << entry->text
624+
<< "', code length: " << user_phrase_code_length;
625+
candidate_source_ = kUserPhrase;
626+
candidate_ =
627+
New<Phrase>(translator_->language(),
628+
entry->IsPredictiveMatch() ? "completion" : "user_phrase",
629+
start_, start_ + user_phrase_code_length, entry);
630+
candidate_->set_quality(std::exp(entry->weight) +
631+
translator_->initial_quality() +
632+
(entry->quality_len / full_code_length));
633+
return true;
634+
} else if (phrase_code_length > 0) {
635+
DictEntryIterator& iter = phrase_iter_->second;
636+
const auto& entry = iter.Peek();
637+
if (!entry) {
638+
++phrase_iter_;
639+
continue;
640+
}
641+
DLOG(INFO) << "phrase '" << entry->text
642+
<< "', code length: " << phrase_code_length;
643+
candidate_source_ = kSysPhrase;
644+
candidate_ =
645+
New<Phrase>(translator_->language(),
646+
entry->IsPredictiveMatch() ? "completion" : "phrase",
647+
start_, start_ + phrase_code_length, entry);
648+
candidate_->set_quality(std::exp(entry->weight) +
649+
translator_->initial_quality() +
650+
(entry->quality_len / full_code_length));
651+
return true;
652+
} else {
653+
candidate_source_ = kUninitialized;
654+
candidate_ = nullptr;
655+
return false;
656+
}
657+
} while (!exhausted() && !candidate_);
658+
return false;
648659
}
649660

650661
bool ScriptTranslation::CheckEmpty() {

0 commit comments

Comments
 (0)