Separate (c), (r), (tm) and emoji.

Fixes #3300.
This commit is contained in:
John Preston 2018-10-24 13:35:53 +04:00
parent 6db4972208
commit e8722e1cb2
4 changed files with 61 additions and 21 deletions

View File

@ -17,6 +17,7 @@ using uint64 = quint64;
using std::vector;
using std::map;
using std::set;
using std::find;
using std::make_pair;
using std::move;
@ -81,6 +82,12 @@ Replace Replaces[] = {
{ { 0xD83DDE08U }, "}:)" },
};
InputCategory PostfixRequired = {
{ 0x2122U, 0xFE0FU, },
{ 0xA9U, 0xFE0FU, },
{ 0xAEU, 0xFE0FU, },
};
using ColorId = uint32;
ColorId Colors[] = {
0xD83CDFFBU,
@ -1904,35 +1911,46 @@ Id BareIdFromInput(const InputId &id) {
return result;
}
using VariatedIds = map<Id, bool>;
VariatedIds fillVariatedIds() {
auto result = VariatedIds();
for (auto &row : ColoredEmoji) {
set<Id> fillVariatedIds() {
auto result = set<Id>();
for (const auto &row : ColoredEmoji) {
auto variatedId = Id();
if (row.size() < 2) {
logDataError() << "colored string should have at least two characters.";
return VariatedIds();
return {};
}
for (auto i = size_t(0), size = row.size(); i != size; ++i) {
auto code = row[i];
if (i == 1) {
if (code != ColorMask) {
logDataError() << "color code should appear at index 1.";
return VariatedIds();
return {};
}
} else if (code == ColorMask) {
logDataError() << "color code should appear only at index 1.";
return VariatedIds();
return {};
} else if (code != kPostfix) {
append(variatedId, code);
}
}
result.insert(make_pair(variatedId, true));
result.emplace(variatedId);
}
return result;
}
void appendCategory(Data &result, const InputCategory &category, const VariatedIds &variatedIds) {
set<Id> fillPostfixRequiredIds() {
auto result = set<Id>();
for (const auto &row : PostfixRequired) {
result.emplace(BareIdFromInput(row));
}
return result;
}
void appendCategory(
Data &result,
const InputCategory &category,
const set<Id> &variatedIds,
const set<Id> &postfixRequiredIds) {
result.categories.push_back(vector<int>());
for (auto &id : category) {
auto emoji = Emoji();
@ -1956,6 +1974,7 @@ void appendCategory(Data &result, const InputCategory &category, const VariatedI
result = Data();
return;
}
auto it = result.map.find(bareId);
if (it == result.map.cend()) {
const auto index = result.list.size();
@ -1964,6 +1983,9 @@ void appendCategory(Data &result, const InputCategory &category, const VariatedI
if (const auto a = Aliases.find(bareId); a != end(Aliases)) {
result.map.emplace(a->second, index);
}
if (postfixRequiredIds.find(bareId) != end(postfixRequiredIds)) {
result.postfixRequired.emplace(index);
}
} else if (result.list[it->second].postfixed != emoji.postfixed) {
logDataError() << "same emoji found with different postfixed property.";
result = Data();
@ -1973,7 +1995,7 @@ void appendCategory(Data &result, const InputCategory &category, const VariatedI
result = Data();
return;
}
if (variatedIds.find(bareId) != variatedIds.cend()) {
if (variatedIds.find(bareId) != end(variatedIds)) {
result.list[it->second].variated = true;
auto baseId = Id();
@ -2003,6 +2025,9 @@ void appendCategory(Data &result, const InputCategory &category, const VariatedI
if (const auto a = Aliases.find(bareColoredId); a != end(Aliases)) {
result.map.emplace(a->second, index);
}
if (postfixRequiredIds.find(bareColoredId) != end(postfixRequiredIds)) {
result.postfixRequired.emplace(index);
}
} else if (result.list[it->second].postfixed != colored.postfixed) {
logDataError() << "same emoji found with different postfixed property.";
result = Data();
@ -2253,8 +2278,9 @@ common::LogStream logDataError() {
Data PrepareData() {
Data result;
auto variatedIds = fillVariatedIds();
if (variatedIds.empty()) {
const auto variatedIds = fillVariatedIds();
const auto postfixRequiredIds = fillPostfixRequiredIds();
if (variatedIds.empty() || postfixRequiredIds.empty()) {
return Data();
}
@ -2277,7 +2303,7 @@ Data PrepareData() {
&Category7,
};
for (const auto category : categories) {
appendCategory(result, *category, variatedIds);
appendCategory(result, *category, variatedIds, postfixRequiredIds);
if (result.list.empty()) {
return Data();
}

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "codegen/common/logging.h"
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <functional>
#include <QtCore/QString>
@ -30,6 +31,7 @@ struct Emoji {
struct Data {
std::vector<Emoji> list;
std::map<Id, int, std::greater<Id>> map;
std::set<int> postfixRequired;
std::vector<std::vector<int>> categories;
std::map<QString, int, std::greater<QString>> replaces;
};

View File

@ -640,7 +640,7 @@ int FindIndex(const QChar *start, const QChar *end, int *outLength) {\n\
auto ch = start;\n\
\n";
if (!writeFindFromDictionary(data_.map, true)) {
if (!writeFindFromDictionary(data_.map, true, data_.postfixRequired)) {
return false;
}
@ -651,7 +651,10 @@ int FindIndex(const QChar *start, const QChar *end, int *outLength) {\n\
return true;
}
bool Generator::writeFindFromDictionary(const std::map<QString, int, std::greater<QString>> &dictionary, bool skipPostfixes) {
bool Generator::writeFindFromDictionary(
const std::map<QString, int, std::greater<QString>> &dictionary,
bool skipPostfixes,
const std::set<int> &postfixRequired) {
auto tabs = [](int size) {
return QString(size, '\t');
};
@ -672,7 +675,7 @@ bool Generator::writeFindFromDictionary(const std::map<QString, int, std::greate
auto checkTypes = QVector<UsedCheckType>();
auto chars = QString();
auto tabsUsed = 1;
auto lengthsCounted = std::map<QString, bool>();
auto lengthsCounted = std::set<QString>();
auto writeSkipPostfix = [this, &tabs, skipPostfixes](int tabsCount) {
if (skipPostfixes) {
@ -728,8 +731,8 @@ bool Generator::writeFindFromDictionary(const std::map<QString, int, std::greate
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));
if (lengthsCounted.find(partialKey) == end(lengthsCounted)) {
lengthsCounted.emplace(partialKey);
source_->stream() << tabs(tabsUsed) << "if (outLength) *outLength = (ch - start);\n";
}
}
@ -752,8 +755,14 @@ bool Generator::writeFindFromDictionary(const std::map<QString, int, std::greate
writeSkipPostfix(++tabsUsed);
chars.push_back(keyChar);
}
if (lengthsCounted.find(key) == lengthsCounted.cend()) {
lengthsCounted.insert(std::make_pair(key, true));
if (postfixRequired.find(item.second) != end(postfixRequired)) {
source_->stream() << tabs(tabsUsed) << "if ((ch - 1)->unicode() != kPostfix) {\n";
source_->stream() << tabs(tabsUsed + 1) << "return 0;\n";
source_->stream() << tabs(tabsUsed) << "}\n";
}
if (lengthsCounted.find(key) == end(lengthsCounted)) {
lengthsCounted.emplace(key);
source_->stream() << tabs(tabsUsed) << "if (outLength) *outLength = (ch - start);\n";
}

View File

@ -48,7 +48,10 @@ private:
bool writeGetSections();
bool writeFindReplace();
bool writeFind();
bool writeFindFromDictionary(const std::map<QString, int, std::greater<QString>> &dictionary, bool skipPostfixes = false);
bool writeFindFromDictionary(
const std::map<QString, int, std::greater<QString>> &dictionary,
bool skipPostfixes = false,
const std::set<int> &postfixRequired = {});
bool writeGetReplacements();
void startBinary();
bool writeStringBinary(common::CppFile *source, const QString &string);