libwordring
atom.hpp
1 #pragma once
2 
3 #include <wordring/compatibility.hpp>
4 #include <wordring/trie/trie.hpp>
5 
6 #include <string>
7 #include <string_view>
8 #include <type_traits>
9 
10 namespace wordring
11 {
12  template <typename String, typename Allocator>
14 }
15 
16 namespace wordring::detail
17 {
27  template <typename String, typename Allocator = std::allocator<detail::trie_node>>
28  class basic_atom : public wordring::stable_trie<typename String::value_type>::const_iterator
29  {
30  template <typename String1, typename Allocator1>
31  friend class wordring::basic_atom_set;
32 
33  template <typename String1, typename Allocator1>
34  friend bool operator==(basic_atom<String1, Allocator1> const&, basic_atom<String1, Allocator1> const&);
35 
36  template <typename String1, typename Allocator1>
37  friend bool operator!=(basic_atom<String1, Allocator1> const&, basic_atom<String1, Allocator1> const&);
38 
39  protected:
41 
42  using typename base_type::container;
43  using typename base_type::index_type;
44  using typename base_type::node_type;
45 
46  public:
47  using string_type = String;
48  using label_type = typename string_type::value_type;
49 
50  using base_type::operator bool;
51  using base_type::operator !;
52  using base_type::string;
53 
54  protected:
55  using base_type::m_c;
56  using base_type::m_index;
57 
58  protected:
63  basic_atom(base_type it)
64  : base_type(it)
65  {
66  }
67 
73  basic_atom(container const& c, index_type idx)
74  : base_type(c, idx)
75  {
76  }
77 
78  public:
88  : base_type()
89  {
90  }
91 
114  operator std::uint32_t() const
115  {
116  typename base_type::index_type idx = 0;
117 
118  if (m_index != 0)
119  {
120  node_type const* d = m_c->data();
121 
122  idx = (d + m_index)->m_base + base_type::null_value;
123  assert(1 < idx && idx < base_type::limit());
124  assert((d + idx)->m_check == m_index);
125  }
126 
127  return idx;
128  }
129 
150  operator string_type() const
151  {
152  string_type result;
153  base_type::string(result);
154  return result;
155  }
156 
182  string_type& string(string_type& result) const
183  {
184  if(m_index != 0) base_type::string(result);
185 
186  return result;
187  }
188  };
189 
190  /* @brief 二つのアトムが等しいか調べる
191 
192  @par 例
193  @code
194  // アトム・コンテナを構築する
195  std::vector<std::u32string> v{ U"あ", U"あう", U"い", U"うあい", U"うえ" };
196  auto as = basic_atom_set<std::u32string>(v.begin(), v.end());
197 
198  // コンテナからアトムを取得する
199  auto a1 = as.at(U"あ");
200  auto a2 = as.at(U"あ");
201 
202  // 二つのアトムが等しいか調べる
203  assert(a1 == a2);
204  @endcode
205  */
206  template <typename String1, typename Allocator1>
207  inline bool operator==(basic_atom<String1, Allocator1> const& lhs, basic_atom<String1, Allocator1> const& rhs)
208  {
209  assert(lhs.m_c == rhs.m_c);
210 
211  return lhs.m_index == rhs.m_index;
212  }
213 
214  /* @brief 二つのアトムが等しくないか調べる
215 
216  @par 例
217  @code
218  // アトム・コンテナを構築する
219  std::vector<std::u32string> v{ U"あ", U"あう", U"い", U"うあい", U"うえ" };
220  auto as = basic_atom_set<std::u32string>(v.begin(), v.end());
221 
222  // コンテナからアトムを取得する
223  auto a1 = as.at(U"あ");
224  auto a2 = as.at(U"あう");
225 
226  // 二つのアトムが等しくないか調べる
227  assert(a1 != a2);
228  @endcode
229  */
230  template <typename String1, typename Allocator1>
231  inline bool operator!=(basic_atom<String1, Allocator1> const& lhs, basic_atom<String1, Allocator1> const& rhs)
232  {
233  assert(lhs.m_c == rhs.m_c);
234 
235  return lhs.m_index != rhs.m_index;
236  }
237 
238 }
239 
240 namespace wordring
241 {
262  template <typename String, typename Allocator = std::allocator<detail::trie_node>>
263  class basic_atom_set : public stable_trie<typename String::value_type>
264  {
265  protected:
266  using base_type = stable_trie<typename String::value_type>;
267 
268  public:
269  using allocator_type = Allocator;
270 
271  using key_type = String;
272  using value_type = detail::basic_atom<key_type>;
273  using label_type = typename String::value_type;
274 
275  using typename base_type::serialize_iterator;
276 
277  using base_type::get_allocator;
278  using base_type::size;
279  using base_type::ibegin;
280  using base_type::iend;
281  using base_type::clear;
282 
283  protected:
284  using base_type::null_value;
285 
286  public:
296  : base_type()
297  {
298  }
299 
310  explicit basic_atom_set(allocator_type const& alloc)
311  : base_type(alloc)
312  {
313  }
314 
342  template <typename InputIterator, typename std::enable_if_t<std::is_integral_v<typename std::iterator_traits<InputIterator>::value_type>, std::nullptr_t> = nullptr>
343  basic_atom_set(InputIterator first, InputIterator last, allocator_type const& alloc = allocator_type())
344  : base_type(alloc)
345  {
346  assign(first, last);
347  }
348 
370  template <typename InputIterator, typename std::enable_if_t<std::negation_v<std::is_integral<typename std::iterator_traits<InputIterator>::value_type>>, std::nullptr_t> = nullptr>
371  basic_atom_set(InputIterator first, InputIterator last, allocator_type const& alloc = allocator_type())
372  : base_type(alloc)
373  {
374  assign(first, last);
375  }
376 
386  basic_atom_set(std::initializer_list<detail::trie_node> il, allocator_type const& alloc = allocator_type())
387  : base_type(il, alloc)
388  {
389  }
390 
414  template <typename InputIterator, typename std::enable_if_t<std::is_integral_v<typename std::iterator_traits<InputIterator>::value_type>, std::nullptr_t> = nullptr>
415  void assign(InputIterator first, InputIterator last)
416  {
417  base_type::assign(first, last);
418  }
419 
440  template <typename InputIterator, typename std::enable_if_t<std::negation_v<std::is_integral<typename std::iterator_traits<InputIterator>::value_type>>, std::nullptr_t> = nullptr>
441  void assign(InputIterator first, InputIterator last)
442  {
443  while (first != last) insert(*first++);
444  }
445 
446  // 要素アクセス --------------------------------------------------------
447 
472  value_type at(std::uint32_t id) const
473  {
474  typename base_type::node_type const* d = base_type::m_c.data();
475 
476  typename base_type::index_type idx = (d + id)->m_check;
477  assert(1 < idx && idx < static_cast<int>(base_type::m_c.size()));
478  assert((d + idx)->m_base + base_type::null_value == id);
479 
480  return value_type(base_type::m_c, idx);
481  }
482 
506  template <typename InputIterator>
507  value_type at(InputIterator first, InputIterator last) const
508  {
509  return base_type::find(first, last);
510  }
511 
533  value_type at(std::basic_string_view<label_type> sv) const
534  {
535  return at(sv.begin(), sv.end());
536  }
537 
557  value_type operator[](std::basic_string_view<label_type> sv)
558  {
559  value_type it = base_type::find(sv.begin(), sv.end());
560  if (!it) it = insert(sv.begin(), sv.end());
561  return it;
562  }
563 
564  // 変更 ---------------------------------------------------------------
565 
587  template <typename InputIterator>
588  value_type insert(InputIterator first, InputIterator last)
589  {
590  auto it = base_type::insert(first, last);
591 
592  typename base_type::index_type idx;
593 
594  if (it)
595  {
596  auto proxy = base_type::at(it, idx);
597  proxy = idx;
598  }
599 
600  return it;
601  }
602 
622  value_type insert(std::basic_string_view<label_type> sv)
623  {
624  return insert(sv.begin(), sv.end());
625  }
626 
648  void erase(std::uint32_t id)
649  {
650  if(id != 0) base_type::erase(static_cast<typename base_type::const_iterator>(at(id)));
651  }
652 
673  template <typename InputIterator>
674  void erase(InputIterator first, InputIterator last)
675  {
676  base_type::erase(base_type::find(first, last));
677  }
678 
697  void erase(std::basic_string_view<label_type> sv)
698  {
699  erase(sv.begin(), sv.end());
700  }
701 
702  // 検索 ---------------------------------------------------------------
703 
711  template <typename InputIterator>
712  bool contains(InputIterator first, InputIterator last) const
713  {
714  return base_type::contains(first, last);
715  }
716 
736  bool contains(std::basic_string_view<label_type> sv) const
737  {
738  return contains(sv.begin(), sv.end());
739  }
740  };
741 
742  template <typename Allocator = std::allocator<detail::trie_node>>
743  using u8atom_set = basic_atom_set<std::u8string, Allocator>;
744 
745  template <typename Allocator = std::allocator<detail::trie_node>>
746  using u16atom_set = basic_atom_set<std::u16string, Allocator>;
747 
748  template <typename Allocator = std::allocator<detail::trie_node>>
749  using u32atom_set = basic_atom_set<std::u32string, Allocator>;
750 }
wordring::basic_atom_set::basic_atom_set
basic_atom_set(std::initializer_list< detail::trie_node > il, allocator_type const &alloc=allocator_type())
初期化子リストから構築する
Definition: atom.hpp:386
wordring::basic_atom_set
文字列アトムのコンテナ
Definition: atom.hpp:13
wordring::basic_atom_set::at
value_type at(std::uint32_t id) const
IDからアトムを返す
Definition: atom.hpp:472
wordring::basic_trie::assign
void assign(InputIterator first, InputIterator last)
直列化データから割り当てる
Definition: trie.hpp:306
wordring::detail::basic_atom
文字列アトム
Definition: atom.hpp:28
wordring::basic_atom_set::erase
void erase(std::uint32_t id)
アトムを削除する
Definition: atom.hpp:648
wordring::detail::basic_atom::basic_atom
basic_atom(container const &c, index_type idx)
アトムを構築する
Definition: atom.hpp:73
wordring::stable_trie
basic_trie< Label, detail::stable_trie_base< Allocator > > stable_trie
葉からの空遷移先INDEXが衝突によって変更されない汎用Trie
Definition: trie.hpp:1034
wordring::basic_atom_set::basic_atom_set
basic_atom_set(allocator_type const &alloc)
アロケータを指定して空のコンテナを構築する
Definition: atom.hpp:310
wordring::basic_trie::find
const_iterator find(InputIterator first, InputIterator last) const
完全一致検索
Definition: trie.hpp:893
wordring::detail::const_trie_iterator
basic_trie のイテレータ
Definition: trie_iterator.hpp:25
wordring
Definition: algorithm_.hpp:10
wordring::basic_trie::at
reference at(const_iterator pos, index_type &idx)
葉の値への参照を返す
Definition: trie.hpp:363
wordring::basic_atom_set::insert
value_type insert(InputIterator first, InputIterator last)
文字列を挿入する
Definition: atom.hpp:588
wordring::basic_trie::size
size_type size() const noexcept
格納しているキー文字列数を調べる
Definition: trie.hpp:601
wordring::basic_trie::contains
bool contains(InputIterator first, InputIterator last) const
キー文字列が格納されているか調べる
Definition: trie.hpp:944
wordring::basic_trie
任意の整数型をラベルとして用いることが出来る汎用Trie
Definition: trie.hpp:130
wordring::basic_atom_set::at
value_type at(InputIterator first, InputIterator last) const
文字列からアトムを返す
Definition: atom.hpp:507
wordring::basic_atom_set::insert
value_type insert(std::basic_string_view< label_type > sv)
文字列を挿入する
Definition: atom.hpp:622
wordring::basic_atom_set::basic_atom_set
basic_atom_set(InputIterator first, InputIterator last, allocator_type const &alloc=allocator_type())
直列化データからの構築
Definition: atom.hpp:343
wordring::detail::basic_atom::string
string_type & string(string_type &result) const
アトムを文字列に変換する
Definition: atom.hpp:182
wordring::basic_atom_set::basic_atom_set
basic_atom_set()
空のコンテナを構築する
Definition: atom.hpp:295
wordring::detail::basic_atom::basic_atom
basic_atom()
空のアトムを構築する
Definition: atom.hpp:87
wordring::basic_atom_set::contains
bool contains(InputIterator first, InputIterator last) const
文字列が格納されているか調べる
Definition: atom.hpp:712
wordring::detail
wordring::basic_atom_set::erase
void erase(std::basic_string_view< label_type > sv)
アトムを削除する
Definition: atom.hpp:697
wordring::basic_atom_set::at
value_type at(std::basic_string_view< label_type > sv) const
文字列からアトムを返す
Definition: atom.hpp:533
wordring::basic_atom_set::erase
void erase(InputIterator first, InputIterator last)
アトムを削除する
Definition: atom.hpp:674
wordring::basic_trie::insert
const_iterator insert(InputIterator first, InputIterator last, value_type value=0)
キー文字列を挿入する
Definition: trie.hpp:644
wordring::detail::basic_atom::basic_atom
basic_atom(base_type it)
アトムを構築する
Definition: atom.hpp:63
wordring::basic_trie::erase
void erase(const_iterator pos)
キー文字列を削除する
Definition: trie.hpp:712
wordring::basic_atom_set::contains
bool contains(std::basic_string_view< label_type > sv) const
文字列が格納されているか調べる
Definition: atom.hpp:736
wordring::basic_atom_set::assign
void assign(InputIterator first, InputIterator last)
直列化データからの割り当て
Definition: atom.hpp:415
wordring::basic_atom_set::operator[]
value_type operator[](std::basic_string_view< label_type > sv)
文字列からアトムを返す
Definition: atom.hpp:557