6 #ifndef _FCITX_LIBIME_CORE_SEGMENTGRAPH_H_ 7 #define _FCITX_LIBIME_CORE_SEGMENTGRAPH_H_ 10 #include <boost/type_traits/add_const.hpp> 18 #include <string_view> 19 #include <unordered_set> 22 #include <boost/iterator/iterator_categories.hpp> 23 #include <boost/iterator/transform_iterator.hpp> 24 #include <boost/range/any_range.hpp> 25 #include <boost/range/iterator_range_core.hpp> 26 #include <fcitx-utils/element.h> 27 #include <fcitx-utils/macros.h> 28 #include <libime/core/libimecore_export.h> 32 class SegmentGraphBase;
33 class SegmentGraphNode;
34 using SegmentGraphDFSCallback =
35 std::function<bool(const SegmentGraphBase &, const std::vector<size_t> &)>;
36 using SegmentGraphBFSCallback =
37 std::function<bool(const SegmentGraphBase &, const SegmentGraphNode *)>;
39 using SegmentGraphNodeRange =
40 boost::any_range<SegmentGraphNode, boost::bidirectional_traversal_tag>;
41 using SegmentGraphNodeConstRange =
42 boost::any_range<
const SegmentGraphNode,
43 boost::bidirectional_traversal_tag>;
45 class LIBIMECORE_EXPORT SegmentGraphNode :
public fcitx::Element {
49 SegmentGraphNode(
size_t start) : start_(start) {}
50 SegmentGraphNode(
const SegmentGraphNode &node) =
delete;
51 virtual ~SegmentGraphNode() {}
53 SegmentGraphNodeConstRange nexts()
const {
54 const auto &nexts = childs();
55 return boost::make_iterator_range(
56 boost::make_transform_iterator(nexts.begin(),
57 &SegmentGraphNode::castConst),
58 boost::make_transform_iterator(nexts.end(),
59 &SegmentGraphNode::castConst));
62 size_t nextSize()
const {
return childs().size(); }
64 SegmentGraphNodeConstRange prevs()
const {
65 const auto &prevs = parents();
66 return boost::make_iterator_range(
67 boost::make_transform_iterator(prevs.begin(),
68 &SegmentGraphNode::castConst),
69 boost::make_transform_iterator(prevs.end(),
70 &SegmentGraphNode::castConst));
73 size_t prevSize()
const {
return parents().size(); }
74 size_t index()
const {
return start_; }
76 bool operator==(
const SegmentGraphNode &other)
const {
77 return this == &other;
79 bool operator!=(
const SegmentGraphNode &other)
const {
80 return !operator==(other);
84 SegmentGraphNodeRange mutablePrevs() {
85 const auto &prevs = parents();
86 return boost::make_iterator_range(
87 boost::make_transform_iterator(prevs.begin(),
88 &SegmentGraphNode::cast),
89 boost::make_transform_iterator(prevs.end(),
90 &SegmentGraphNode::cast));
93 SegmentGraphNodeRange mutableNexts() {
94 const auto &nexts = childs();
95 return boost::make_iterator_range(
96 boost::make_transform_iterator(nexts.begin(),
97 &SegmentGraphNode::cast),
98 boost::make_transform_iterator(nexts.end(),
99 &SegmentGraphNode::cast));
102 void addEdge(SegmentGraphNode &ref) {
103 assert(ref.start_ > start_);
106 void removeEdge(SegmentGraphNode &ref) { removeChild(&ref); }
108 static auto castConst(fcitx::Element *ele) ->
const SegmentGraphNode & {
109 return *
static_cast<SegmentGraphNode *
>(ele);
111 static auto cast(fcitx::Element *ele) -> SegmentGraphNode & {
112 return *
static_cast<SegmentGraphNode *
>(ele);
119 using SegmentGraphPath = std::vector<const SegmentGraphNode *>;
120 using DiscardCallback =
121 std::function<void(const std::unordered_set<const SegmentGraphNode *> &)>;
128 virtual const SegmentGraphNode &start()
const = 0;
129 virtual const SegmentGraphNode &end()
const = 0;
131 virtual SegmentGraphNodeConstRange nodes(
size_t idx)
const = 0;
132 const SegmentGraphNode &node(
size_t idx)
const {
133 return nodes(idx).front();
137 const std::string &data()
const {
return data_; }
140 size_t size()
const {
return data().size(); }
142 std::string_view segment(
size_t start,
size_t end)
const {
143 return {data().data() + start, end - start};
146 std::string_view segment(
const SegmentGraphNode &start,
147 const SegmentGraphNode &end)
const {
148 return segment(start.index(), end.index());
151 bool bfs(
const SegmentGraphNode *from,
152 const SegmentGraphBFSCallback &callback)
const;
154 bool dfs(
const SegmentGraphDFSCallback &callback)
const {
155 std::vector<size_t> path;
156 return dfsHelper(path, start(), callback);
160 size_t distanceToEnd(
const SegmentGraphNode &node)
const {
161 const auto *pNode = &node;
162 const SegmentGraphNode *endNode = &end();
164 while (pNode != endNode) {
165 pNode = &pNode->nexts().front();
171 bool isList()
const {
172 const SegmentGraphNode *node = &start();
173 const SegmentGraphNode *endNode = &end();
174 while (node != endNode) {
175 if (node->nextSize() != 1) {
178 node = &node->nexts().front();
183 bool checkGraph()
const {
184 std::unordered_set<const SegmentGraphNode *> allNodes;
185 for (
size_t i = 0, e = size(); i < e; i++) {
186 for (
const auto &n : nodes(i)) {
187 if (n.nexts().empty() && n != end()) {
195 const SegmentGraphNode *node) {
196 allNodes.erase(node);
200 return allNodes.empty();
203 bool checkNodeInGraph(
const SegmentGraphNode *node)
const {
204 for (
size_t i = 0, e = size(); i <= e; i++) {
205 for (
const auto &n : nodes(i)) {
215 std::string &mutableData() {
return data_; }
218 bool dfsHelper(std::vector<size_t> &path,
const SegmentGraphNode &start,
219 const SegmentGraphDFSCallback &callback)
const {
220 if (start == end()) {
221 return callback(*
this, path);
223 auto nexts = start.nexts();
224 for (
const auto &next : nexts) {
225 auto idx = next.index();
227 if (!dfsHelper(path, next, callback)) {
241 resize(data().size() + 1);
242 if (!data().empty()) {
243 newNode(data().size());
248 FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_MOVE_WITHOUT_SPEC(
SegmentGraph)
250 const SegmentGraphNode &start()
const override {
return *graph_[0]; }
251 const SegmentGraphNode &end()
const override {
252 return *graph_[data().size()];
255 const DiscardCallback &discardCallback = {});
257 SegmentGraphNode &ensureNode(
size_t idx) {
258 if (nodes(idx).empty()) {
261 return mutableNode(idx);
264 SegmentGraphNodeConstRange nodes(
size_t idx)
const override {
265 assert(idx < graph_.size());
267 return {graph_[idx].get(), graph_[idx].get() + 1};
271 using SegmentGraphBase::node;
274 void addNext(
size_t from,
size_t to) {
276 assert(to <= data().size());
277 if (nodes(from).empty()) {
280 if (nodes(to).empty()) {
283 graph_[from]->addEdge(*graph_[to]);
286 void appendNewSegment(std::string_view str) {
292 size_t oldSize = data().size();
293 mutableData().append(str.data(), str.size());
294 resize(data().size() + 1);
295 auto &newEnd = newNode(data().size());
296 auto &node = mutableNode(oldSize);
297 node.addEdge(newEnd);
300 void appendToLastSegment(std::string_view str) {
306 size_t oldSize = data().size();
307 mutableData().append(str.data(), str.size());
308 resize(data().size() + 1);
310 auto &newEnd = newNode(data().size());
311 auto &node = mutableNode(oldSize);
314 node.addEdge(newEnd);
320 for (
auto &prev : node.mutablePrevs()) {
321 prev.addEdge(newEnd);
324 graph_[oldSize].reset();
327 void removeSuffixFrom(
size_t idx) {
332 auto *pNode = &mutableNode(size());
333 const auto *pStart = &start();
334 while (pNode != pStart && pNode->index() > idx) {
335 pNode = &pNode->mutablePrevs().front();
338 mutableData().erase(idx);
339 resize(data().size() + 1);
344 if (pNode->index() == idx) {
347 auto &newEnd = newNode(size());
348 pNode->addEdge(newEnd);
352 void resize(
size_t newSize) {
353 auto oldSize = graph_.size();
354 graph_.resize(newSize);
355 for (; oldSize < newSize; oldSize++) {
356 graph_[oldSize].reset();
360 SegmentGraphNode &newNode(
size_t idx) {
361 graph_[idx] = std::make_unique<SegmentGraphNode>(idx);
365 SegmentGraphNode &mutableNode(
size_t idx) {
366 return mutableNodes(idx).front();
369 SegmentGraphNodeRange mutableNodes(
size_t idx) {
370 assert(idx < graph_.size());
372 return {graph_[idx].get(), graph_[idx].get() + 1};
379 std::vector<std::unique_ptr<SegmentGraphNode>> graph_;
383 #endif // _FCITX_LIBIME_CORE_SEGMENTGRAPH_H_