Fcitx
handlertable_details.h
1 /*
2  * SPDX-FileCopyrightText: 2016-2016 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 #ifndef _FCITX_UTILS_HANDLERTABLE_DETAILS_H_
8 #define _FCITX_UTILS_HANDLERTABLE_DETAILS_H_
9 
10 // IWYU pragma: private, include <fcitx-utils/handlertable.h>
11 
12 #include <cstddef>
13 #include <iterator>
14 #include <memory>
15 #include <vector>
16 #include <fcitx-utils/fcitxutils_export.h>
17 #include <fcitx-utils/intrusivelist.h>
18 #include <fcitx-utils/macros.h>
19 
20 namespace fcitx {
21 
22 class FCITXUTILS_EXPORT HandlerTableEntryBase {
23 public:
24  virtual ~HandlerTableEntryBase() = default;
25 };
26 
27 // Ugly hack since we don't want to maintain optional.
28 template <typename T>
29 using HandlerTableData = std::shared_ptr<std::unique_ptr<T>>;
30 
31 // Handler Tables are a kind of helper class that helps manage callbacks
32 // HandlerTableEntry can be deleted
33 template <typename T>
35 
36 public:
37  template <typename... Args>
38  HandlerTableEntry(Args &&...args)
39  : handler_(std::make_shared<std::unique_ptr<T>>(
40  std::make_unique<T>(std::forward<Args>(args)...))) {}
41  ~HandlerTableEntry() override { handler_->reset(); }
42 
43  HandlerTableData<T> handler() const { return handler_; }
44 
45 protected:
46  HandlerTableData<T> handler_;
47 };
48 
49 template <typename T>
51  IntrusiveListNode node_;
52  friend struct IntrusiveListMemberNodeGetter<
53  ListHandlerTableEntry<T>, &ListHandlerTableEntry<T>::node_>;
54 
55 public:
56  using node_getter_type =
57  struct IntrusiveListMemberNodeGetter<ListHandlerTableEntry,
58  &ListHandlerTableEntry::node_>;
59 
60  template <typename... Args>
61  ListHandlerTableEntry(Args &&...args)
62  : HandlerTableEntry<T>(std::forward<Args>(args)...) {}
63  virtual ~ListHandlerTableEntry() { node_.remove(); }
64 };
65 
66 template <typename Key, typename T>
67 class MultiHandlerTable;
68 
69 template <typename Key, typename T>
72 
73 private:
74  table_type *table_;
75  Key key_;
76  IntrusiveListNode node_;
77  friend struct IntrusiveListMemberNodeGetter<MultiHandlerTableEntry,
78  &MultiHandlerTableEntry::node_>;
79 
80 public:
81  using node_getter_type =
82  struct IntrusiveListMemberNodeGetter<MultiHandlerTableEntry,
83  &MultiHandlerTableEntry::node_>;
84  MultiHandlerTableEntry(table_type *table, Key key, T handler)
85  : HandlerTableEntry<T>(std::move(handler)), table_(table),
86  key_(std::move(key)) {}
87  ~MultiHandlerTableEntry();
88 };
89 
90 template <typename Key, typename T>
92  if (node_.isInList()) {
93  node_.remove();
94  table_->postRemove(key_);
95  }
96 }
97 
98 template <typename T>
99 class HandlerTableView {
100  using container_type = std::vector<HandlerTableData<T>>;
101 
102 public:
103  HandlerTableView() = default;
104 
105  template <typename _Iter>
106  HandlerTableView(_Iter begin, _Iter end) {
107  for (; begin != end; begin++) {
108  view_.emplace_back(begin->handler());
109  }
110  }
111 
112  class iterator {
113  public:
114  using iterator_category = std::input_iterator_tag;
115  using value_type = T;
116  using difference_type = std::ptrdiff_t;
117  using reference = value_type &;
118  using pointer = value_type *;
119 
120  iterator() = default;
121 
122  iterator(typename container_type::const_iterator iter,
123  typename container_type::const_iterator end)
124  : parentIter_(iter), endIter_(end) {
125  while (parentIter_ != endIter_ && !*parentIter_ && !**parentIter_) {
126  parentIter_++;
127  }
128  }
129 
130  FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_COPY(iterator)
131 
132  bool operator==(const iterator &other) const noexcept {
133  return parentIter_ == other.parentIter_;
134  }
135  bool operator!=(const iterator &other) const noexcept {
136  return !operator==(other);
137  }
138 
139  iterator &operator++() {
140  do {
141  ++parentIter_;
142  // *parentIter_ is the shared_ptr, should never be null.
143  // **parentIter_ is the optional value, may be null if
144  // HandlerEntry is deleted.
145  } while (parentIter_ != endIter_ && !(**parentIter_));
146  return *this;
147  }
148 
149  iterator operator++(int) {
150  auto old = parentIter_;
151  ++(*this);
152  return {old, endIter_};
153  }
154 
155  reference operator*() const { return ***parentIter_; }
156 
157  pointer operator->() const { return (**parentIter_).get(); }
158 
159  private:
160  typename container_type::const_iterator parentIter_;
161  typename container_type::const_iterator endIter_;
162  };
163 
164  iterator begin() const { return iterator(view_.cbegin(), view_.cend()); }
165  iterator end() const { return iterator(view_.cend(), view_.cend()); }
166 
167 private:
168  std::vector<HandlerTableData<T>> view_;
169 };
170 } // namespace fcitx
171 
172 #endif // _FCITX_UTILS_HANDLERTABLE_DETAILS_H_
Describe a Key in fcitx.
Definition: key.h:41
Definition: action.cpp:17