mirror of https://github.com/procxx/kepka.git
				
				
				
			Revert "Rewrite emoji switch-based search"
As it introduces emoji regression.
This reverts commit b2ee90263d.
			
			
This commit is contained in:
		
							parent
							
								
									2d2a39ff41
								
							
						
					
					
						commit
						47535632ee
					
				| 
						 | 
					@ -610,24 +610,13 @@ EmojiPack GetSection(Section section) {\n\
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Generator::writeFindReplace() {
 | 
					bool Generator::writeFindReplace() {
 | 
				
			||||||
	source_->stream() << "\
 | 
					 | 
				
			||||||
const std::map<QString, int> ReplaceMap = {\n\
 | 
					 | 
				
			||||||
\n";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (auto &item : data_.replaces) {
 | 
					 | 
				
			||||||
		source_->stream() << "{\"" << item.first << "\"," << item.second << "},\n";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	source_->stream() << "\
 | 
					 | 
				
			||||||
\n\
 | 
					 | 
				
			||||||
};\n";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	source_->stream() << "\
 | 
						source_->stream() << "\
 | 
				
			||||||
\n\
 | 
					\n\
 | 
				
			||||||
int FindReplaceIndex(const QChar *start, const QChar *end, int *outLength) {\n\
 | 
					int FindReplaceIndex(const QChar *start, const QChar *end, int *outLength) {\n\
 | 
				
			||||||
	auto ch = start;\n\
 | 
						auto ch = start;\n\
 | 
				
			||||||
\n";
 | 
					\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!writeFindFromDictionary(data_.replaces, "ReplaceMap")) {
 | 
						if (!writeFindFromDictionary(data_.replaces)) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -639,22 +628,12 @@ int FindReplaceIndex(const QChar *start, const QChar *end, int *outLength) {\n\
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Generator::writeFind() {
 | 
					bool Generator::writeFind() {
 | 
				
			||||||
	source_->stream() << "\
 | 
						source_->stream() << "\
 | 
				
			||||||
const std::map<QString, int> EmojiMap = {\n\
 | 
					 | 
				
			||||||
\n";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (auto &item : data_.map) {
 | 
					 | 
				
			||||||
		source_->stream() << "{\"" << item.first << "\"," << item.second << "},\n";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	source_->stream() << "\
 | 
					 | 
				
			||||||
\n\
 | 
					 | 
				
			||||||
};\n";
 | 
					 | 
				
			||||||
	source_->stream() << "\
 | 
					 | 
				
			||||||
\n\
 | 
					\n\
 | 
				
			||||||
int FindIndex(const QChar *start, const QChar *end, int *outLength) {\n\
 | 
					int FindIndex(const QChar *start, const QChar *end, int *outLength) {\n\
 | 
				
			||||||
	auto ch = start;\n\
 | 
						auto ch = start;\n\
 | 
				
			||||||
\n";
 | 
					\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!writeFindFromDictionary(data_.map, "EmojiMap", true)) {
 | 
						if (!writeFindFromDictionary(data_.map, true)) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -664,42 +643,127 @@ int FindIndex(const QChar *start, const QChar *end, int *outLength) {\n\
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
bool Generator::writeFindFromDictionary(const std::map<QString, int, std::greater<QString>> &dictionary,
 | 
					 | 
				
			||||||
                                        QString dict_name, bool skipPostfixes) {
 | 
					 | 
				
			||||||
	source_->stream() << R"code(	QString full_str(start, end-start), str="";
 | 
					 | 
				
			||||||
)code";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto max_el = std::max_element(dictionary.begin(), dictionary.end(),
 | 
					bool Generator::writeFindFromDictionary(const std::map<QString, int, std::greater<QString>> &dictionary,
 | 
				
			||||||
	                               [](const auto &a, const auto &b) { return a.first.size() < b.first.size(); });
 | 
					                                        bool skipPostfixes) {
 | 
				
			||||||
	auto max_length = max_el->first.size();
 | 
						auto tabs = [](int size) { return QString(size, '\t'); };
 | 
				
			||||||
	source_->stream() << "\tstd::array<size_t, " << max_length + 1 << "> sizes;\n";
 | 
					
 | 
				
			||||||
	if (skipPostfixes) {
 | 
						std::map<int, int> uniqueFirstChars;
 | 
				
			||||||
		source_->stream() << "\tfor (int i=0,l=0; i<str.size() && l < " << max_length << R"code(; ++i) {
 | 
						auto foundMax = 0, foundMin = 65535;
 | 
				
			||||||
		if (str[i] == kPostfix) {continue;}
 | 
						for (auto &item : dictionary) {
 | 
				
			||||||
		++l;
 | 
							auto ch = item.first[0].unicode();
 | 
				
			||||||
		sizes[l]=i;
 | 
							if (foundMax < ch) foundMax = ch;
 | 
				
			||||||
		str+=full_str[i];
 | 
							if (foundMin > ch) foundMin = ch;
 | 
				
			||||||
 | 
							uniqueFirstChars[ch] = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
)code";
 | 
					
 | 
				
			||||||
	} else {
 | 
						enum class UsedCheckType {
 | 
				
			||||||
		source_->stream() << "\tstd::iota(sizes.begin(), sizes.end(), 0);\n";
 | 
							Switch,
 | 
				
			||||||
		source_->stream() << "\tstr = full_str.mid(0," << max_length << ");\n";
 | 
							If,
 | 
				
			||||||
	}
 | 
						};
 | 
				
			||||||
	source_->stream() << R"code(	for (int curr_len = str.size(); curr_len>0; --curr_len) {
 | 
						auto checkTypes = QVector<UsedCheckType>();
 | 
				
			||||||
		QString substr = str.mid(0,curr_len);
 | 
						auto chars = QString();
 | 
				
			||||||
		if ()code" << dict_name
 | 
						auto tabsUsed = 1;
 | 
				
			||||||
	                  << ".find(substr) !=" << dict_name << R"code(.end()) {
 | 
						auto lengthsCounted = std::map<QString, bool>();
 | 
				
			||||||
			if (outLength) *outLength = sizes[curr_len];
 | 
					
 | 
				
			||||||
			return )code"
 | 
						auto writeSkipPostfix = [this, &tabs, skipPostfixes](int tabsCount) {
 | 
				
			||||||
	                  << dict_name << R"code(.at(substr);
 | 
							if (skipPostfixes) {
 | 
				
			||||||
 | 
								source_->stream() << tabs(tabsCount) << "if (++ch != end && ch->unicode() == kPostfix) ++ch;\n";
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								source_->stream() << tabs(tabsCount) << "++ch;\n";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Returns true if at least one check was finished.
 | 
				
			||||||
 | 
						auto finishChecksTillKey = [this, &chars, &checkTypes, &tabsUsed, tabs](const QString &key) {
 | 
				
			||||||
 | 
							auto result = false;
 | 
				
			||||||
 | 
							while (!chars.isEmpty() && key.midRef(0, chars.size()) != chars) {
 | 
				
			||||||
 | 
								result = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto wasType = checkTypes.back();
 | 
				
			||||||
 | 
								chars.resize(chars.size() - 1);
 | 
				
			||||||
 | 
								checkTypes.pop_back();
 | 
				
			||||||
 | 
								if (wasType == UsedCheckType::Switch || wasType == UsedCheckType::If) {
 | 
				
			||||||
 | 
									--tabsUsed;
 | 
				
			||||||
 | 
									if (wasType == UsedCheckType::Switch) {
 | 
				
			||||||
 | 
										source_->stream() << tabs(tabsUsed) << "break;\n";
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if ((!chars.isEmpty() && key.midRef(0, chars.size()) != chars) || key == chars) {
 | 
				
			||||||
 | 
										source_->stream() << tabs(tabsUsed) << "}\n";
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if we can use "if" for a check on "charIndex" in "it" (otherwise only "switch")
 | 
				
			||||||
 | 
						auto canUseIfForCheck = [](auto it, auto end, int charIndex) {
 | 
				
			||||||
 | 
							auto key = it->first;
 | 
				
			||||||
 | 
							auto i = it;
 | 
				
			||||||
 | 
							auto keyStart = key.mid(0, charIndex);
 | 
				
			||||||
 | 
							for (++i; i != end; ++i) {
 | 
				
			||||||
 | 
								auto nextKey = i->first;
 | 
				
			||||||
 | 
								if (nextKey.mid(0, charIndex) != keyStart) {
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								} else if (nextKey.size() > charIndex && nextKey[charIndex] != key[charIndex]) {
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto i = dictionary.cbegin(), e = dictionary.cend(); i != e; ++i) {
 | 
				
			||||||
 | 
							auto &item = *i;
 | 
				
			||||||
 | 
							auto key = item.first;
 | 
				
			||||||
 | 
							auto weContinueOldSwitch = finishChecksTillKey(key);
 | 
				
			||||||
 | 
							while (chars.size() != key.size()) {
 | 
				
			||||||
 | 
								auto checking = chars.size();
 | 
				
			||||||
 | 
								auto partialKey = key.mid(0, checking);
 | 
				
			||||||
 | 
								if (dictionary.find(partialKey) != dictionary.cend()) {
 | 
				
			||||||
 | 
									if (lengthsCounted.find(partialKey) == lengthsCounted.cend()) {
 | 
				
			||||||
 | 
										lengthsCounted.insert(std::make_pair(partialKey, true));
 | 
				
			||||||
 | 
										source_->stream() << tabs(tabsUsed) << "if (outLength) *outLength = (ch - start);\n";
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto keyChar = key[checking];
 | 
				
			||||||
 | 
								auto keyCharString = "0x" + QString::number(keyChar.unicode(), 16);
 | 
				
			||||||
 | 
								auto usedIfForCheck = !weContinueOldSwitch && canUseIfForCheck(i, e, checking);
 | 
				
			||||||
 | 
								if (weContinueOldSwitch) {
 | 
				
			||||||
 | 
									weContinueOldSwitch = false;
 | 
				
			||||||
 | 
								} else if (!usedIfForCheck) {
 | 
				
			||||||
 | 
									source_->stream() << tabs(tabsUsed) << "if (ch != end) switch (ch->unicode()) {\n";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (usedIfForCheck) {
 | 
				
			||||||
 | 
									source_->stream() << tabs(tabsUsed) << "if (ch != end && ch->unicode() == " << keyCharString << ") {\n";
 | 
				
			||||||
 | 
									checkTypes.push_back(UsedCheckType::If);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									source_->stream() << tabs(tabsUsed) << "case " << keyCharString << ":\n";
 | 
				
			||||||
 | 
									checkTypes.push_back(UsedCheckType::Switch);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								writeSkipPostfix(++tabsUsed);
 | 
				
			||||||
 | 
								chars.push_back(keyChar);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (lengthsCounted.find(key) == lengthsCounted.cend()) {
 | 
				
			||||||
 | 
								lengthsCounted.insert(std::make_pair(key, true));
 | 
				
			||||||
 | 
								source_->stream() << tabs(tabsUsed) << "if (outLength) *outLength = (ch - start);\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// While IsReplaceEdge() currently is always true we just return the value.
 | 
				
			||||||
 | 
							// source_->stream() << tabs(1 + chars.size()) << "if (ch + " << chars.size() << " == end || IsReplaceEdge(*(ch
 | 
				
			||||||
 | 
							// + " << chars.size() << ")) || (ch + " << chars.size() << ")->unicode() == ' ') {\n"; source_->stream() <<
 | 
				
			||||||
 | 
							// tabs(1 + chars.size()) << "\treturn &Items[" << item.second << "];\n"; source_->stream() << tabs(1 +
 | 
				
			||||||
 | 
							// chars.size()) << "}\n";
 | 
				
			||||||
 | 
							source_->stream() << tabs(tabsUsed) << "return " << (item.second + 1) << ";\n";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						finishChecksTillKey(QString());
 | 
				
			||||||
)code";
 | 
					
 | 
				
			||||||
 | 
						source_->stream() << "\
 | 
				
			||||||
 | 
					\n\
 | 
				
			||||||
 | 
						return 0;\n";
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Generator::writeSuggestionsSource() {
 | 
					bool Generator::writeSuggestionsSource() {
 | 
				
			||||||
	suggestionsSource_ = std::make_unique<common::CppFile>(suggestionsPath_ + ".cpp", project_);
 | 
						suggestionsSource_ = std::make_unique<common::CppFile>(suggestionsPath_ + ".cpp", project_);
 | 
				
			||||||
	suggestionsSource_->stream() << "\
 | 
						suggestionsSource_->stream() << "\
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,7 +60,7 @@ private:
 | 
				
			||||||
	bool writeGetSections();
 | 
						bool writeGetSections();
 | 
				
			||||||
	bool writeFindReplace();
 | 
						bool writeFindReplace();
 | 
				
			||||||
	bool writeFind();
 | 
						bool writeFind();
 | 
				
			||||||
	bool writeFindFromDictionary(const std::map<QString, int, std::greater<QString>> &dictionary, QString dict_name,
 | 
						bool writeFindFromDictionary(const std::map<QString, int, std::greater<QString>> &dictionary,
 | 
				
			||||||
	                             bool skipPostfixes = false);
 | 
						                             bool skipPostfixes = false);
 | 
				
			||||||
	bool writeGetReplacements();
 | 
						bool writeGetReplacements();
 | 
				
			||||||
	void startBinary();
 | 
						void startBinary();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue