Spicy
stream.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <hilti/ast/expressions/id.h>
6 #include <hilti/ast/operators/common.h>
7 #include <hilti/ast/types/bool.h>
8 #include <hilti/ast/types/bytes.h>
9 #include <hilti/ast/types/integer.h>
10 #include <hilti/ast/types/stream.h>
11 
12 namespace hilti::operator_ {
13 
14 // stream::Iterator
15 
16 STANDARD_OPERATOR_1(stream::iterator, Deref, type::UnsignedInteger(64), type::constant(type::stream::Iterator()),
17  "Returns the character the iterator is pointing to.");
18 STANDARD_OPERATOR_1(stream::iterator, IncrPostfix, type::stream::Iterator(), type::stream::Iterator(),
19  "Advances the iterator by one byte, returning the previous position.");
20 STANDARD_OPERATOR_1(stream::iterator, IncrPrefix, type::stream::Iterator(), type::stream::Iterator(),
21  "Advances the iterator by one byte, returning the new position.");
22 
23 STANDARD_OPERATOR_2(
24  stream::iterator, Equal, type::Bool(), type::constant(type::stream::Iterator()),
25  type::constant(type::stream::Iterator()),
26  "Compares the two positions. The result is undefined if they are not referring to the same stream value.");
27 STANDARD_OPERATOR_2(
28  stream::iterator, Unequal, type::Bool(), type::constant(type::stream::Iterator()),
29  type::constant(type::stream::Iterator()),
30  "Compares the two positions. The result is undefined if they are not referring to the same stream value.");
31 STANDARD_OPERATOR_2(
32  stream::iterator, Lower, type::Bool(), type::constant(type::stream::Iterator()),
33  type::constant(type::stream::Iterator()),
34  "Compares the two positions. The result is undefined if they are not referring to the same stream value.");
35 STANDARD_OPERATOR_2(
36  stream::iterator, LowerEqual, type::Bool(), type::constant(type::stream::Iterator()),
37  type::constant(type::stream::Iterator()),
38  "Compares the two positions. The result is undefined if they are not referring to the same stream value.");
39 STANDARD_OPERATOR_2(
40  stream::iterator, Greater, type::Bool(), type::constant(type::stream::Iterator()),
41  type::constant(type::stream::Iterator()),
42  "Compares the two positions. The result is undefined if they are not referring to the same stream value.");
43 STANDARD_OPERATOR_2(
44  stream::iterator, GreaterEqual, type::Bool(), type::constant(type::stream::Iterator()),
45  type::constant(type::stream::Iterator()),
46  "Compares the two positions. The result is undefined if they are not referring to the same stream value.");
47 STANDARD_OPERATOR_2(
48  stream::iterator, Difference, type::SignedInteger(64), type::constant(type::stream::Iterator()),
49  type::constant(type::stream::Iterator()),
50  "Returns the number of stream between the two iterators. The result will be negative if the second iterator points "
51  "to a location before the first. The result is undefined if the iterators do not refer to the same stream "
52  "instance.");
53 STANDARD_OPERATOR_2(stream::iterator, Sum, type::stream::Iterator(), type::constant(type::stream::Iterator()),
54  type::UnsignedInteger(64), "Advances the iterator by the given number of stream.")
55 STANDARD_OPERATOR_2(stream::iterator, SumAssign, type::stream::Iterator(), type::stream::Iterator(),
56  type::UnsignedInteger(64), "Advances the iterator by the given number of stream.")
57 
58 BEGIN_METHOD(stream::iterator, Offset)
59  const auto& signature() const {
60  static auto _signature = Signature{.self = type::constant(type::stream::Iterator()),
61  .result = type::UnsignedInteger(64),
62  .id = "offset",
63  .args = {},
64  .doc = R"(
65 Returns the offset of the byte that the iterator refers to relative to the
66 beginning of the underlying stream value.
67 )"};
68  return _signature;
69  }
70 END_METHOD
71 
72 BEGIN_METHOD(stream::iterator, IsFrozen)
73  const auto& signature() const {
74  static auto _signature = Signature{.self = type::constant(type::stream::Iterator()),
75  .result = type::Bool(),
76  .id = "is_frozen",
77  .args = {},
78  .doc = R"(
79 Returns whether the stream value that the iterator refers to has been frozen.
80 )"};
81  return _signature;
82  }
83 END_METHOD
84 
85 // stream::View
86 
87 STANDARD_OPERATOR_1(stream::view, Size, type::UnsignedInteger(64), type::constant(type::stream::View()),
88  "Returns the number of stream the view contains.");
89 STANDARD_OPERATOR_2x(stream::view, InBytes, In, type::Bool(), type::constant(type::stream::View()),
90  type::constant(type::Bytes()),
91  "Returns true if the right-hand-side view contains the left-hand-side bytes as a subsequence.");
92 STANDARD_OPERATOR_2x(stream::view, InView, In, type::Bool(), type::constant(type::Bytes()),
93  type::constant(type::stream::View()),
94  "Returns true if the right-hand-side bytes contains the left-hand-side view as a subsequence.");
95 STANDARD_OPERATOR_2x(stream::view, EqualView, Equal, type::Bool(), type::constant(type::stream::View()),
96  type::constant(type::stream::View()), "Compares the views lexicographically.");
97 STANDARD_OPERATOR_2x(stream::view, EqualBytes, Equal, type::Bool(), type::constant(type::stream::View()),
98  type::constant(type::Bytes()), "Compares a stream view and a bytes instance lexicographically.");
99 STANDARD_OPERATOR_2x(stream::view, UnequalView, Unequal, type::Bool(), type::constant(type::stream::View()),
100  type::constant(type::stream::View()), "Compares two views lexicographically.");
101 STANDARD_OPERATOR_2x(stream::view, UnequalBytes, Unequal, type::Bool(), type::constant(type::stream::View()),
102  type::constant(type::Bytes()), "Compares a stream view and a bytes instance lexicographically.");
103 
104 BEGIN_METHOD(stream::view, Offset)
105  const auto& signature() const {
106  static auto _signature = Signature{.self = type::constant(type::stream::View()),
107  .result = type::UnsignedInteger(64),
108  .id = "offset",
109  .args = {},
110  .doc = R"(
111 Returns the offset of the view's starting position within the associated stream value.
112 )"};
113  return _signature;
114  }
115 END_METHOD
116 
117 BEGIN_METHOD(stream::view, AdvanceBy)
118  const auto& signature() const {
119  static auto _signature = Signature{.self = type::constant(type::stream::View()),
120  .result = type::stream::View(),
121  .id = "advance",
122  .args = {{"i", type::stream::Iterator()}},
123  .doc = R"(
124 Advances the view's starting position to a given iterator *i*, returning the new
125 view. The iterator must be referring to the same stream values as the view, and
126 it must be equal or ahead of the view's starting position.
127 )"};
128  return _signature;
129  }
130 END_METHOD
131 
132 BEGIN_METHOD(stream::view, AdvanceToNextData)
133  const auto& signature() const {
134  static auto _signature = Signature{.self = type::constant(type::stream::View()),
135  .result = type::stream::View(),
136  .id = "advance_to_next_data",
137  .args = {},
138  .doc = R"(
139 Advances the view's starting position to the next non-gap position. This always
140 advances the input by at least one byte.
141 )"};
142  return _signature;
143  }
144 END_METHOD
145 
146 BEGIN_METHOD(stream::view, Limit)
147  const auto& signature() const {
148  static auto _signature = Signature{.self = type::constant(type::stream::View()),
149  .result = type::stream::View(),
150  .id = "limit",
151  .args = {{"i", type::UnsignedInteger(64)}},
152  .doc = R"(
153 Returns a new view that keeps the current start but cuts off the end *i*
154 characters from that beginning. The returned view will not be able to expand any
155 further.
156 )"};
157  return _signature;
158  }
159 END_METHOD
160 
161 BEGIN_METHOD(stream::view, AdvanceTo)
162  const auto& signature() const {
163  static auto _signature = Signature{.self = type::constant(type::stream::View()),
164  .result = type::stream::View(),
165  .id = "advance",
166  .args = {{"i", type::UnsignedInteger(64)}},
167  .doc = R"(
168 Advances the view's starting position by *i* stream, returning the new view.
169 )"};
170  return _signature;
171  }
172 END_METHOD
173 
174 BEGIN_METHOD(stream::view, Find)
175  const auto& signature() const {
176  static auto _signature = Signature{.self = type::constant(type::stream::View()),
177  .result = type::Tuple({type::Bool(), type::stream::Iterator()}),
178  .id = "find",
179  .args = {{"needle", type::constant(type::Bytes())}},
180  .doc = R"(
181 Searches *needle* inside the view's content. Returns a tuple of a boolean and an
182 iterator. If *needle* was found, the boolean will be true and the iterator will point
183 to its first occurrence. If *needle* was not found, the boolean will be false and
184 the iterator will point to the last position so that everything before that is
185 guaranteed to not contain even a partial match of *needle* (in other words: one can
186 trim until that position and then restart the search from there if more data
187 gets appended to the underlying stream value). Note that for a simple yes/no result,
188 you should use the ``in`` operator instead of this method, as it's more efficient.
189 )"};
190  return _signature;
191  }
192 END_METHOD
193 
194 BEGIN_METHOD(stream::view, At)
195  const auto& signature() const {
196  static auto _signature = Signature{.self = type::constant(type::stream::View()),
197  .result = type::stream::Iterator(),
198  .id = "at",
199  .args = {{"i", type::UnsignedInteger(64)}},
200  .doc = R"(
201 Returns an iterator representing the offset *i* inside the view.
202 )"};
203  return _signature;
204  }
205 END_METHOD
206 
207 BEGIN_METHOD(stream::view, StartsWith)
208  const auto& signature() const {
209  static auto _signature = Signature{.self = type::constant(type::stream::View()),
210  .result = type::Bool(),
211  .id = "starts_with",
212  .args = {{"b", type::constant(type::Bytes())}},
213  .doc = R"(
214 Returns true if the view starts with *b*.
215 )"};
216  return _signature;
217  }
218 END_METHOD
219 
220 BEGIN_METHOD(stream::view, SubIterators)
221  const auto& signature() const {
222  static auto _signature =
223  Signature{.self = type::constant(type::stream::View()),
224  .result = type::stream::View(),
225  .id = "sub",
226  .args = {{"begin", type::stream::Iterator()}, {"end", type::stream::Iterator()}},
227  .doc = R"(
228 Returns a new view of the subsequence from *begin* up to (but not including)
229 *end*.
230 )"};
231  return _signature;
232  }
233 END_METHOD
234 
235 BEGIN_METHOD(stream::view, SubIterator)
236  const auto& signature() const {
237  static auto _signature = Signature{.self = type::constant(type::stream::View()),
238  .result = type::stream::View(),
239  .id = "sub",
240  .args = {{"end", type::stream::Iterator()}},
241  .doc = R"(
242 Returns a new view of the subsequence from the beginning of the stream up to
243 (but not including) *end*.
244 )"};
245  return _signature;
246  }
247 END_METHOD
248 
249 BEGIN_METHOD(stream::view, SubOffsets)
250  const auto& signature() const {
251  static auto _signature =
252  Signature{.self = type::constant(type::stream::View()),
253  .result = type::stream::View(),
254  .id = "sub",
255  .args = {{"begin", type::UnsignedInteger(64)}, {"end", type::UnsignedInteger(64)}},
256  .doc = R"(
257 Returns a new view of the subsequence from offset *begin* to (but not including)
258 offset *end*. The offsets are relative to the beginning of the view.
259 )"};
260  return _signature;
261  }
262 END_METHOD
263 
264 // Stream
265 
266 STANDARD_OPERATOR_1(stream, Size, type::UnsignedInteger(64), type::constant(type::Stream()),
267  "Returns the number of stream the value contains.");
268 STANDARD_OPERATOR_2(stream, Unequal, type::Bool(), type::constant(type::Stream()), type::constant(type::Stream()),
269  "Compares two stream values lexicographically.");
270 STANDARD_OPERATOR_2x(stream, SumAssignView, SumAssign, type::Stream(), type::Stream(),
271  type::constant(type::stream::View()), "Concatenates another stream's view to the target stream.");
272 STANDARD_OPERATOR_2x(stream, SumAssignBytes, SumAssign, type::Stream(), type::Stream(), type::constant(type::Bytes()),
273  "Concatenates data to the stream.");
274 
275 BEGIN_METHOD(stream, Freeze)
276  const auto& signature() const {
277  static auto _signature =
278  Signature{.self = type::Stream(), .result = type::void_, .id = "freeze", .args = {}, .doc = R"(
279 Freezes the stream value. Once frozen, one cannot append any more data to a
280 frozen stream value (unless it gets unfrozen first). If the value is
281 already frozen, the operation does not change anything.
282 )"};
283  return _signature;
284  }
285 END_METHOD
286 
287 BEGIN_METHOD(stream, Unfreeze)
288  const auto& signature() const {
289  static auto _signature =
290  Signature{.self = type::Stream(), .result = type::void_, .id = "unfreeze", .args = {}, .doc = R"(
291 Unfreezes the stream value. A unfrozen stream value can be further modified. If
292 the value is already unfrozen (which is the default), the operation does not
293 change anything.
294 )"};
295  return _signature;
296  }
297 END_METHOD
298 
299 BEGIN_METHOD(stream, IsFrozen)
300  const auto& signature() const {
301  static auto _signature = Signature{.self = type::constant(type::Stream()),
302  .result = type::Bool(),
303  .id = "is_frozen",
304  .args = {},
305  .doc = R"(
306 Returns true if the stream value has been frozen.
307 )"};
308  return _signature;
309  }
310 END_METHOD
311 
312 BEGIN_METHOD(stream, At)
313  const auto& signature() const {
314  static auto _signature = Signature{.self = type::constant(type::Stream()),
315  .result = type::stream::Iterator(),
316  .id = "at",
317  .args = {{"i", type::UnsignedInteger(64)}},
318  .doc = R"(
319 Returns an iterator representing the offset *i* inside the stream value.
320 )"};
321  return _signature;
322  }
323 END_METHOD
324 
325 BEGIN_METHOD(stream, Trim)
326  const auto& signature() const {
327  static auto _signature = Signature{.self = type::Stream(),
328  .result = type::void_,
329  .id = "trim",
330  .args = {{"i", type::stream::Iterator()}},
331  .doc = R"(
332 Trims the stream value by removing all data from its beginning up to (but not
333 including) the position *i*. The iterator *i* will remain valid afterwards and
334 will still point to the same location, which will now be the beginning of the stream's
335 value. All existing iterators pointing to *i* or beyond will remain valid and keep
336 their offsets as well. The effect of this operation is undefined if *i* does not
337 actually refer to a location inside the stream value. Trimming is permitted
338 even on frozen values.
339 )"};
340  return _signature;
341  }
342 END_METHOD
343 
344 } // namespace hilti::operator_
Definition: operator-registry.h:15