libwordring
terminology.hpp
1 #pragma once
2 
3 #include <algorithm>
4 #include <deque>
5 #include <iterator>
6 #include <optional>
7 #include <vector>
8 
9 // ------------------------------------------------------------------------------------------------
10 // 3. Terminology
11 //
12 // https://encoding.spec.whatwg.org/#terminology
13 // https://triple-underscore.github.io/Encoding-ja.html#terminology
14 // ------------------------------------------------------------------------------------------------
15 
17 {
25  template <typename T>
26  struct io_item
27  {
28  T m_value = T();
29  bool m_eoq = false;
30 
31  T& operator*() { return m_value; }
32  };
33 
36  template <typename T>
37  struct io_result
38  {
39  using value_type = T;
40 
41  value_type m_value;
42  bool m_wait = false;
43 
44  T* operator->() { return &m_value; }
45  T& operator*() { return m_value; }
46  };
47 
54  template <typename T>
55  class io_queue
56  {
57  public:
58  using value_type = io_item<T>;
59  using character_type = T;
60 
61  public:
62  io_queue() : m_q() {}
63 
80  {
81  if (m_q.empty()) return io_result<value_type>{ value_type{}, true };
82 
83  value_type c = m_q.front();
84  if (c.m_eoq) return io_result<value_type>{ c, false };
85  m_q.pop_front();
86  return io_result<value_type>{ c, false };
87  }
88 
107  {
108  // 1.
109  std::vector<value_type> readItems;
110  // 規格に追加
111  if (m_q.size() < n) return { readItems, true }; // 待機を返す
112  // 2.
113  for (std::uint32_t i = 0; i < n; ++i) readItems.push_back(*read());
114  // 3.
115  if (readItems.back().m_eoq) readItems.pop_back();
116  // 4.
117  return { readItems, false };
118  }
119 
126  {
127  assert(1 <= n);
128 
129  // 1.
130  if (m_q.size() < n && !(!m_q.empty() && m_q.back().m_eoq)) return { {}, true };
131  // 2.
132  std::vector<value_type> prefix;
133  // 3.
134  for (value_type const& p : m_q)
135  {
136  if (p.m_eoq) break;
137  prefix.push_back(p);
138  }
139  // 4.
140  return { prefix, false };
141  }
142 
152  void push(value_type item)
153  {
154  // 1.
155  if (!m_q.empty() && m_q.back().m_eoq)
156  {
157  if (item.m_eoq);
158  else m_q.insert(--m_q.end(), item);
159  }
160  // 2.
161  else m_q.push_back(item);
162  }
163 
164  void push(T ch)
165  {
166  push(value_type{ ch, false });
167  }
168 
169  template <typename InputIterator>
170  void push(InputIterator first, InputIterator last)
171  {
172  while (first != last)
173  {
174  push(*first);
175  ++first;
176  }
177  }
178 
183  void prepend(value_type item)
184  {
185  //assert(!item.m_eoq); ISO2022_JP が EOQ を挿入する場合がある。
186  m_q.push_front(item);
187  }
188 
193  void prepend(T ch)
194  {
195  prepend(value_type{ ch, false });
196  }
197 
202  template <typename InputIterator>
203  void prepend(InputIterator first, InputIterator last)
204  {
205  auto it = m_q.begin();
206  while (first != last) it = ++m_q.insert(it, value_type{ static_cast<T>(*first++), false });
207  }
208 
209  private:
210  std::deque<value_type> m_q;
211  };
212 
222  template <typename T, typename OutputIterator>
223  inline void from_io_queue_convert(io_queue<T> q, OutputIterator out)
224  {
225  while (true)
226  {
227  auto item = q.read();
228  if (item.m_wait || item->m_eoq) return;
229  *out++ = **item;
230  }
231  }
232 
237  template <typename InputIterator>
238  inline auto to_io_queue_convert(InputIterator first, InputIterator last)
239  {
240  using value_type = typename std::iterator_traits<InputIterator>::value_type;
242  q.push(first, last);
243  q.push({ 0, true });
244  return q;
245  }
246 }
wordring::whatwg::encoding::io_queue::peek
io_result< std::vector< value_type > > peek(std::uint32_t n)
Peek
Definition: terminology.hpp:125
wordring::whatwg::encoding
wordring::whatwg::encoding::io_queue::prepend
void prepend(value_type item)
Prepend
Definition: terminology.hpp:183
wordring::whatwg::encoding::io_item
文字にキュー終端表現を追加するラッパー
Definition: terminology.hpp:26
wordring::whatwg::encoding::from_io_queue_convert
void from_io_queue_convert(io_queue< T > q, OutputIterator out)
io_queue を文字列へ変換する
Definition: terminology.hpp:223
wordring::whatwg::encoding::io_queue::read
io_result< std::vector< value_type > > read(std::uint32_t n)
値を読み取る
Definition: terminology.hpp:106
wordring::whatwg::encoding::to_io_queue_convert
auto to_io_queue_convert(InputIterator first, InputIterator last)
文字列を io_queue へ変換する
Definition: terminology.hpp:238
wordring::whatwg::encoding::io_queue::push
void push(value_type item)
Push
Definition: terminology.hpp:152
wordring::whatwg::encoding::io_queue::prepend
void prepend(T ch)
Prepend
Definition: terminology.hpp:193
wordring::whatwg::encoding::io_queue
入出力ストリーム
Definition: terminology.hpp:55
wordring::whatwg::encoding::io_queue::read
io_result< value_type > read()
値を一つ読み取る
Definition: terminology.hpp:79
wordring::whatwg::encoding::io_result
待機状態を追加するラッパー
Definition: terminology.hpp:37
wordring::whatwg::encoding::io_queue::prepend
void prepend(InputIterator first, InputIterator last)
Prepend
Definition: terminology.hpp:203