14 #include <string_view> 17 #include <fcitx-utils/charutils.h> 18 #include <fcitx-utils/stringutils.h> 19 #include "libime/core/utils_p.h" 25 constexpr
int TAIL_OFFSET = 0x80;
27 int8_t toIndex(uint8_t index) {
28 if (index < TAIL_OFFSET) {
31 return -
static_cast<int8_t
>(index - TAIL_OFFSET + 1);
34 uint8_t fromIndex(int8_t index) {
38 return (-index) + TAIL_OFFSET - 1;
43 TableRuleEntry::TableRuleEntry(TableRuleEntryFlag flag, uint8_t character,
44 uint8_t encodingIndex)
45 : flag_(flag), character_(character), encodingIndex_(encodingIndex) {}
47 TableRuleEntry::TableRuleEntry(std::istream &in) {
48 throw_if_io_fail(unmarshall(in, flag_));
49 throw_if_io_fail(unmarshall(in, character_));
50 throw_if_io_fail(unmarshall(in, encodingIndex_));
53 bool TableRuleEntry::isPlaceHolder()
const {
54 return character_ == 0 || index() == 0;
57 int TableRuleEntry::index()
const {
return toIndex(encodingIndex_); }
59 TableRule::TableRule(
const std::string &ruleString,
unsigned int maxLength) {
61 throw std::invalid_argument(
"invalid rule string");
64 switch (ruleString[0]) {
67 flag_ = TableRuleFlag::LengthEqual;
72 flag_ = TableRuleFlag::LengthLongerThan;
76 throw std::invalid_argument(
"invalid rule string");
79 auto equalSignPos = ruleString.find(
'=', 1);
80 if (equalSignPos == std::string::npos) {
81 throw std::invalid_argument(
"invalid rule string");
84 auto afterEqualSign = std::string_view(ruleString).substr(equalSignPos + 1);
85 std::vector<std::string> entryStrings =
86 fcitx::stringutils::split(afterEqualSign,
"+");
87 if (entryStrings.empty() || entryStrings.size() > maxLength) {
88 throw std::invalid_argument(
"invalid rule string");
91 auto beforeEqualSign = std::string_view(ruleString).substr(0, equalSignPos);
92 if (beforeEqualSign.size() != 2 ||
93 !fcitx::charutils::isdigit(beforeEqualSign[1])) {
94 throw std::invalid_argument(
"invalid rule string");
97 phraseLength_ = beforeEqualSign[1] -
'0';
98 if (phraseLength_ <= 0 || phraseLength_ > maxLength) {
99 throw std::invalid_argument(
"Invalid phrase length");
102 for (
const auto &entryString : entryStrings) {
103 TableRuleEntryFlag entryFlag;
104 switch (entryString[0]) {
107 entryFlag = TableRuleEntryFlag::FromFront;
111 entryFlag = TableRuleEntryFlag::FromBack;
114 throw std::invalid_argument(
"invalid rule entry flag");
117 if (entryString.size() != 3 ||
118 !fcitx::charutils::isdigit(entryString[1]) ||
119 !(fcitx::charutils::isdigit(entryString[2]) ||
120 fcitx::charutils::isupper(entryString[2]) ||
121 fcitx::charutils::islower(entryString[2]))) {
122 throw std::invalid_argument(
"invalid rule entry");
125 int8_t character = entryString[1] -
'0';
127 if (fcitx::charutils::isdigit(entryString[2])) {
128 index = entryString[2] -
'0';
130 index = fcitx::charutils::tolower(entryString[2]) -
'z' - 1;
132 if (character < 0 || character > static_cast<int>(maxLength) ||
133 std::abs(index) > static_cast<int>(maxLength) ||
134 ((character == 0) ^ (index == 0))) {
135 throw std::invalid_argument(
"invalid rule entry");
139 TableRuleEntry(entryFlag, character, fromIndex(index)));
142 TableRule::TableRule(TableRuleFlag _flag,
int _phraseLength,
143 std::vector<TableRuleEntry> _entries)
144 : flag_(_flag), phraseLength_(_phraseLength),
145 entries_(std::move(_entries)) {}
146 TableRule::TableRule(std::istream &in) {
148 throw_if_io_fail(unmarshall(in, flag_));
149 throw_if_io_fail(unmarshall(in, phraseLength_));
150 throw_if_io_fail(unmarshall(in, size));
151 entries_.reserve(size);
152 for (
auto i = 0U; i < size; i++) {
153 entries_.emplace_back(in);
157 std::string TableRule::name()
const {
159 result += ((flag_ == TableRuleFlag::LengthEqual) ?
'e' :
'a');
160 result += std::to_string(phraseLength_);
165 std::string TableRule::toString()
const {
171 for (
const auto &entry : entries_) {
177 result += ((entry.flag() == TableRuleEntryFlag::FromFront) ?
'p' :
'n');
178 result +=
static_cast<char>(
'0' + entry.character());
179 auto index = entry.index();
181 result +=
static_cast<char>(
'0' + index);
183 result +=
static_cast<char>(
'z' + index + 1);
189 size_t TableRule::codeLength()
const {
191 for (
const auto &entry : entries_) {
192 if (entry.isPlaceHolder()) {
200 std::ostream &operator<<(std::ostream &out,
const TableRuleEntry &r) {
201 if (!marshall(out, r.flag())) {
204 if (!marshall(out, r.character())) {
207 if (!marshall(out, r.encodingIndex())) {
213 std::ostream &operator<<(std::ostream &out,
const TableRule &r) {
214 if (marshall(out, r.flag()) && marshall(out, r.phraseLength()) &&
215 marshall(out, static_cast<uint32_t>(r.entries().size()))) {
216 for (
const auto &entry : r.entries()) {
217 if (!(out << entry)) {