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