diff --git a/src/libime/core/datrie.cpp b/src/libime/core/datrie.cpp index a91852b..462ab20 100644 --- a/src/libime/core/datrie.cpp +++ b/src/libime/core/datrie.cpp @@ -77,6 +77,13 @@ struct NanValue { } }; +template +constexpr inline T decodeImpl(int32_t raw) { + typename DATriePrivate::decoder_type d; + d.result = raw; + return d.result_value; +} + } // namespace #if 0 @@ -352,16 +359,6 @@ class DATriePrivate { to = from; } } - value_type traverse(const char *key, npos_t &from, size_t &pos) const { - return traverse(key, from, pos, std::strlen(key)); - } - - value_type traverse(const char *key, npos_t &from, size_t &pos, - size_t len) const { - decoder_type d; - d.result = _find(key, from, pos, len); - return d.result_value; - } template inline void update(const char *key, const U &callback) { @@ -534,13 +531,13 @@ class DATriePrivate { } bool foreach(const callback_type &callback, npos_t root = npos_t()) const { - decoder_type b; + int32_t resultRaw; size_t p(0); npos_t from = root; - for (b.result = begin(from, p); b.result != CEDAR_NO_PATH; - b.result = next(from, p, root)) { - if (b.result != CEDAR_NO_VALUE && - !callback(b.result_value, p, from.toInt())) { + for (resultRaw = begin(from, p); resultRaw != CEDAR_NO_PATH; + resultRaw = next(from, p, root)) { + if (resultRaw != CEDAR_NO_VALUE && + !callback(decodeImpl(resultRaw), p, from.toInt())) { return false; } } @@ -1111,14 +1108,18 @@ bool DATrie::erase(position_type from) { template typename DATrie::value_type DATrie::exactMatchSearch(const char *key, size_t len) const { + return decodeImpl(exactMatchSearchRaw(key, len)); +} + +template +int32_t DATrie::exactMatchSearchRaw(const char *key, size_t len) const { size_t pos = 0; typename DATriePrivate::npos_t npos; - typename DATriePrivate::decoder_type decoder; - decoder.result = d->_find(key, npos, pos, len); - if (decoder.result == DATriePrivate::CEDAR_NO_PATH) { - decoder.result = DATriePrivate::CEDAR_NO_VALUE; + auto resultRaw = d->_find(key, npos, pos, len); + if (resultRaw == DATriePrivate::CEDAR_NO_PATH) { + resultRaw = DATriePrivate::CEDAR_NO_VALUE; } - return decoder.result_value; + return resultRaw; } template @@ -1129,9 +1130,15 @@ bool DATrie::hasExactMatch(std::string_view key) const { template typename DATrie::value_type DATrie::traverse(const char *key, size_t len, position_type &from) const { + return decodeImpl(traverseRaw(key, len, from)); +} + +template +int32_t DATrie::traverseRaw(const char *key, size_t len, + position_type &from) const { size_t pos = 0; typename DATriePrivate::npos_t npos(from); - auto result = d->traverse(key, npos, pos, len); + auto result = d->_find(key, npos, pos, len); from = npos.toInt(); return result; } @@ -1150,33 +1157,51 @@ template bool DATrie::isNoPath(value_type v) { typename DATriePrivate::decoder_type d; d.result_value = v; - return d.result == DATriePrivate::CEDAR_NO_PATH; + return isNoPathRaw(d.result); } template bool DATrie::isNoValue(value_type v) { typename DATriePrivate::decoder_type d; d.result_value = v; - return d.result == DATriePrivate::CEDAR_NO_VALUE; + return isNoValueRaw(d.result); } template bool DATrie::isValid(value_type v) { - return !(isNoPath(v) || isNoValue(v)); + typename DATriePrivate::decoder_type d; + d.result_value = v; + return isValidRaw(d.result); +} + +template +bool DATrie::isNoPathRaw(int32_t v) { + return v == DATriePrivate::CEDAR_NO_PATH; +} + +template +bool DATrie::isNoValueRaw(int32_t v) { + return v == DATriePrivate::CEDAR_NO_VALUE; +} + +template +bool DATrie::isValidRaw(int32_t v) { + return !(isNoPathRaw(v) || isNoValueRaw(v)); } template T DATrie::noPath() { - typename DATriePrivate::decoder_type d; - d.result = DATriePrivate::CEDAR_NO_PATH; - return d.result_value; + return decodeImpl(DATriePrivate::CEDAR_NO_PATH); } template T DATrie::noValue() { - typename DATriePrivate::decoder_type d; - d.result = DATriePrivate::CEDAR_NO_VALUE; - return d.result_value; + return decodeImpl(DATriePrivate::CEDAR_NO_VALUE); +} + +template +T DATrie::decode(int32_t raw) { + return decodeImpl(raw); } template diff --git a/src/libime/core/datrie.h b/src/libime/core/datrie.h index d47a76e..65f9cf5 100644 --- a/src/libime/core/datrie.h +++ b/src/libime/core/datrie.h @@ -90,6 +90,11 @@ class DATrie { return exactMatchSearch(key.data(), key.size()); } + int32_t exactMatchSearchRaw(const char *key, size_t len) const; + int32_t exactMatchSearchRaw(std::string_view key) const { + return exactMatchSearchRaw(key.data(), key.size()); + } + bool hasExactMatch(std::string_view key) const; DATrie::value_type traverse(std::string_view key, @@ -99,6 +104,11 @@ class DATrie { DATrie::value_type traverse(const char *key, size_t len, position_type &from) const; + int32_t traverseRaw(std::string_view key, position_type &from) const { + return traverseRaw(key.data(), key.size(), from); + } + int32_t traverseRaw(const char *key, size_t len, position_type &from) const; + // set value void set(std::string_view key, value_type val) { return set(key.data(), key.size(), val); @@ -138,9 +148,15 @@ class DATrie { static bool isNoPath(value_type v); static bool isNoValue(value_type v); + static bool isValidRaw(int32_t v); + static bool isNoPathRaw(int32_t v); + static bool isNoValueRaw(int32_t v); + static value_type noPath(); static value_type noValue(); + static value_type decode(int32_t raw); + size_t mem_size() const; private: diff --git a/src/libime/pinyin/pinyindictionary.cpp b/src/libime/pinyin/pinyindictionary.cpp index 43dec58..b6d636d 100644 --- a/src/libime/pinyin/pinyindictionary.cpp +++ b/src/libime/pinyin/pinyindictionary.cpp @@ -17,6 +17,8 @@ #include "pinyinmatchstate_p.h" #include #include +#include +#include #include #include #include @@ -158,10 +160,10 @@ inline void searchOneStep( auto iter = nodes.begin(); while (iter != nodes.end()) { if (current != 0) { - PinyinTrie::value_type result; - result = iter->first->traverse(¤t, 1, iter->second); + const auto resultRaw = + iter->first->traverseRaw(¤t, 1, iter->second); - if (PinyinTrie::isNoPath(result)) { + if (PinyinTrie::isNoPathRaw(resultRaw)) { nodes.erase(iter++); } else { iter++; @@ -171,8 +173,8 @@ inline void searchOneStep( for (char test = PinyinEncoder::firstFinal; test <= PinyinEncoder::lastFinal; test++) { decltype(extraNodes)::value_type p = *iter; - auto result = p.first->traverse(&test, 1, p.second); - if (!PinyinTrie::isNoPath(result)) { + const auto resultRaw = p.first->traverseRaw(&test, 1, p.second); + if (!PinyinTrie::isNoPathRaw(resultRaw)) { extraNodes.push_back(p); changed = true; } @@ -371,8 +373,8 @@ PinyinTriePositions traverseAlongPathOneStepBySyllables( // make a copy auto pos = _pos; auto initial = static_cast(syl.first); - auto result = path.trie()->traverse(&initial, 1, pos); - if (PinyinTrie::isNoPath(result)) { + const auto resultRaw = path.trie()->traverseRaw(&initial, 1, pos); + if (PinyinTrie::isNoPathRaw(resultRaw)) { continue; } const auto &finals = syl.second; @@ -381,9 +383,9 @@ PinyinTriePositions traverseAlongPathOneStepBySyllables( size_t fuzzyFactor, auto pos) { auto final = static_cast(pyFinal); - auto result = path.trie()->traverse(&final, 1, pos); + const auto resultRaw = path.trie()->traverseRaw(&final, 1, pos); - if (!PinyinTrie::isNoPath(result)) { + if (!PinyinTrie::isNoPathRaw(resultRaw)) { size_t newFuzzies = fuzzies + fuzzyFactor; positions.emplace_back(pos, newFuzzies); } @@ -446,8 +448,8 @@ void matchWordsOnTrie(const PinyinTrie *userDict, const MatchedPinyinPath &path, pos); } else { const char sep = pinyinHanziSep; - auto result = path.trie()->traverse(&sep, 1, pos); - if (PinyinTrie::isNoPath(result)) { + const auto resultRaw = path.trie()->traverseRaw(&sep, 1, pos); + if (PinyinTrie::isNoPathRaw(resultRaw)) { continue; } diff --git a/src/libime/pinyin/pinyindictionary.h b/src/libime/pinyin/pinyindictionary.h index 937d80e..fd1c744 100644 --- a/src/libime/pinyin/pinyindictionary.h +++ b/src/libime/pinyin/pinyindictionary.h @@ -7,10 +7,20 @@ #define _FCITX_LIBIME_PINYIN_PINYINDICTIONARY_H_ #include "libimepinyin_export.h" +#include +#include #include +#include +#include +#include +#include #include #include #include +#include +#include +#include +#include namespace libime { @@ -18,9 +28,8 @@ enum class PinyinDictFormat { Text, Binary }; class PinyinDictionaryPrivate; -typedef std::function - PinyinMatchCallback; +using PinyinMatchCallback = + std::function; using PinyinTrie = typename TrieDictionary::TrieType; @@ -64,7 +73,7 @@ class LIBIMEPINYIN_EXPORT PinyinDictionary : public TrieDictionary { void save(size_t idx, std::ostream &out, PinyinDictFormat format); void addWord(size_t idx, std::string_view fullPinyin, - std::string_view hanzi, float cost = 0.0f); + std::string_view hanzi, float cost = 0.0F); bool removeWord(size_t idx, std::string_view fullPinyin, std::string_view hanzi); std::optional lookupWord(size_t idx, std::string_view fullPinyin, diff --git a/src/libime/table/tablebaseddictionary.cpp b/src/libime/table/tablebaseddictionary.cpp index c68d0ed..4a9bcf2 100644 --- a/src/libime/table/tablebaseddictionary.cpp +++ b/src/libime/table/tablebaseddictionary.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -275,7 +276,7 @@ bool TableBasedDictionaryPrivate::matchTrie( auto curPos = position; auto strCode = fcitx::utf8::UCS4ToUTF8(code); auto result = trie.traverse(strCode, curPos); - if (!trie.isNoPath(result)) { + if (!DATrie::isNoPath(result)) { newPositions.push_back(curPos); } } @@ -286,7 +287,7 @@ bool TableBasedDictionaryPrivate::matchTrie( std::distance(charRange.first, charRange.second)); auto curPos = position; auto result = trie.traverse(chr, curPos); - if (!trie.isNoPath(result)) { + if (!DATrie::isNoPath(result)) { newPositions.push_back(curPos); } } diff --git a/test/testtrie.cpp b/test/testtrie.cpp index b811850..ba715c7 100644 --- a/test/testtrie.cpp +++ b/test/testtrie.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "libime/core/datrie.h" +#include #include #include @@ -39,8 +40,8 @@ int main() { FCITX_ASSERT(trie.size() == 4); DATrie::position_type pos = 0; auto result = trie.traverse("aaa", pos); - auto nan1 = trie.noValue(); - auto nan2 = trie.noPath(); + auto nan1 = DATrie::noValue(); + auto nan2 = DATrie::noPath(); // NaN != NaN, we must use memcmp to do this. FCITX_ASSERT(memcmp(&nan1, &result, sizeof(float)) == 0); FCITX_ASSERT(trie.isNoValue(result));