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(typename container_type::const_iterator iter,
121  typename container_type::const_iterator end)
122  : parentIter_(iter), endIter_(end) {
123  while (parentIter_ != endIter_ && !*parentIter_ && !**parentIter_) {
124  parentIter_++;
125  }
126  }
127 
128  FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_COPY(iterator)
129 
130  bool operator==(const iterator &other) const noexcept {
131  return parentIter_ == other.parentIter_;
132  }
133  bool operator!=(const iterator &other) const noexcept {
134  return !operator==(other);
135  }
136 
137  iterator &operator++() {
138  do {
139  ++parentIter_;
140  // *parentIter_ is the shared_ptr, should never be null.
141  // **parentIter_ is the optional value, may be null if
142  // HandlerEntry is deleted.
143  } while (parentIter_ != endIter_ && !(**parentIter_));
144  return *this;
145  }
146 
147  iterator operator++(int) {
148  auto old = parentIter_;
149  ++(*this);
150  return {old, endIter_};
151  }
152 
153  reference operator*() { return ***parentIter_; }
154 
155  pointer operator->() { return (**parentIter_).get(); }
156 
157  private:
158  typename container_type::const_iterator parentIter_;
159  typename container_type::const_iterator endIter_;
160  };
161 
162  iterator begin() const { return iterator(view_.cbegin(), view_.cend()); }
163  iterator end() const { return iterator(view_.cend(), view_.cend()); }
164 
165 private:
166  std::vector<HandlerTableData<T>> view_;
167 };
168 } // namespace fcitx
169 
170 #endif // _FCITX_UTILS_HANDLERTABLE_DETAILS_H_
Describe a Key in fcitx.
Definition: key.h:41
Definition: action.cpp:17