autoc 1.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGES.md +3 -0
- data/README.md +149 -0
- data/cmake/AutoC.cmake +39 -0
- data/lib/autoc/allocators.rb +51 -0
- data/lib/autoc/association.rb +126 -0
- data/lib/autoc/box.rb +311 -0
- data/lib/autoc/cmake.rb +54 -0
- data/lib/autoc/collection.rb +83 -110
- data/lib/autoc/composite.rb +333 -0
- data/lib/autoc/cstring.rb +263 -0
- data/lib/autoc/function.rb +247 -0
- data/lib/autoc/hash_map.rb +328 -0
- data/lib/autoc/hash_set.rb +339 -0
- data/lib/autoc/hashers.rb +102 -0
- data/lib/autoc/list.rb +444 -0
- data/lib/autoc/module.rb +434 -0
- data/lib/autoc/openmp.rb +15 -0
- data/lib/autoc/primitive.rb +27 -0
- data/lib/autoc/ranges.rb +707 -0
- data/lib/autoc/record.rb +247 -0
- data/lib/autoc/scaffold/docs.rb +117 -0
- data/lib/autoc/scaffold/generic_value.rb +86 -0
- data/lib/autoc/scaffold/project.rb +75 -0
- data/lib/autoc/scaffold/test_cstring.rb +113 -0
- data/lib/autoc/scaffold/test_cstring_hash_set.rb +35 -0
- data/lib/autoc/scaffold/test_int_box.rb +22 -0
- data/lib/autoc/scaffold/test_int_hash_set.rb +448 -0
- data/lib/autoc/scaffold/test_int_list.rb +106 -0
- data/lib/autoc/scaffold/test_int_vector.rb +83 -0
- data/lib/autoc/scaffold/test_v2v_hash_map.rb +83 -0
- data/lib/autoc/scaffold/test_value_hash_set.rb +60 -0
- data/lib/autoc/scaffold/test_value_vector.rb +146 -0
- data/{test/test.rb → lib/autoc/scaffold/tests.rb} +179 -158
- data/lib/autoc/scaffold.rb +12 -0
- data/lib/autoc/sequential.rb +99 -0
- data/lib/autoc/set.rb +331 -0
- data/lib/autoc/std.rb +149 -0
- data/lib/autoc/type.rb +93 -531
- data/lib/autoc/vector.rb +290 -0
- data/lib/autoc.rb +4 -35
- metadata +55 -85
- data/.yardopts +0 -4
- data/CHANGES +0 -23
- data/README +0 -28
- data/doc/AutoC/Code.html +0 -523
- data/doc/AutoC/Collection.html +0 -1214
- data/doc/AutoC/HashMap.html +0 -1441
- data/doc/AutoC/HashSet.html +0 -916
- data/doc/AutoC/Iterators/Bidirectional.html +0 -204
- data/doc/AutoC/Iterators/Unidirectional.html +0 -200
- data/doc/AutoC/Iterators.html +0 -126
- data/doc/AutoC/List.html +0 -1039
- data/doc/AutoC/Maps.html +0 -290
- data/doc/AutoC/Module/File.html +0 -415
- data/doc/AutoC/Module/Header.html +0 -437
- data/doc/AutoC/Module/Source.html +0 -707
- data/doc/AutoC/Module.html +0 -948
- data/doc/AutoC/Priority.html +0 -138
- data/doc/AutoC/Queue.html +0 -1172
- data/doc/AutoC/Reference.html +0 -735
- data/doc/AutoC/Sets.html +0 -520
- data/doc/AutoC/String.html +0 -1394
- data/doc/AutoC/TreeMap.html +0 -1565
- data/doc/AutoC/TreeSet.html +0 -1447
- data/doc/AutoC/Type.html +0 -2148
- data/doc/AutoC/UserDefinedType.html +0 -1047
- data/doc/AutoC/Vector.html +0 -987
- data/doc/AutoC.html +0 -331
- data/doc/_index.html +0 -388
- data/doc/class_list.html +0 -51
- data/doc/css/common.css +0 -1
- data/doc/css/full_list.css +0 -58
- data/doc/css/style.css +0 -481
- data/doc/file.CHANGES.html +0 -117
- data/doc/file.README.html +0 -116
- data/doc/file_list.html +0 -61
- data/doc/frames.html +0 -17
- data/doc/index.html +0 -116
- data/doc/js/app.js +0 -243
- data/doc/js/full_list.js +0 -216
- data/doc/js/jquery.js +0 -4
- data/doc/method_list.html +0 -1307
- data/doc/top-level-namespace.html +0 -112
- data/lib/autoc/code.rb +0 -237
- data/lib/autoc/collection/hash_map.rb +0 -385
- data/lib/autoc/collection/hash_set.rb +0 -337
- data/lib/autoc/collection/iterator.rb +0 -39
- data/lib/autoc/collection/list.rb +0 -429
- data/lib/autoc/collection/map.rb +0 -41
- data/lib/autoc/collection/queue.rb +0 -517
- data/lib/autoc/collection/set.rb +0 -134
- data/lib/autoc/collection/tree_map.rb +0 -464
- data/lib/autoc/collection/tree_set.rb +0 -611
- data/lib/autoc/collection/vector.rb +0 -336
- data/lib/autoc/string.rb +0 -492
- data/test/test_auto.c +0 -7141
- data/test/test_auto.h +0 -753
- data/test/test_char_string.rb +0 -270
- data/test/test_int_list.rb +0 -35
- data/test/test_int_tree_set.rb +0 -111
- data/test/test_int_vector.rb +0 -34
- data/test/test_value_hash_map.rb +0 -162
- data/test/test_value_hash_set.rb +0 -173
- data/test/test_value_list.rb +0 -193
- data/test/test_value_queue.rb +0 -275
- data/test/test_value_tree_map.rb +0 -176
- data/test/test_value_tree_set.rb +0 -173
- data/test/test_value_vector.rb +0 -155
- data/test/value.rb +0 -80
data/lib/autoc/ranges.rb
ADDED
@@ -0,0 +1,707 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
require 'autoc/std'
|
5
|
+
require 'autoc/composite'
|
6
|
+
|
7
|
+
|
8
|
+
module AutoC
|
9
|
+
|
10
|
+
|
11
|
+
using STD::Coercions
|
12
|
+
|
13
|
+
|
14
|
+
# @abstract
|
15
|
+
class Range < Composite
|
16
|
+
|
17
|
+
attr_reader :iterable
|
18
|
+
|
19
|
+
def default_constructible? = false
|
20
|
+
def destructible? = false
|
21
|
+
def comparable? = false
|
22
|
+
def orderable? = false
|
23
|
+
def copyable? = false
|
24
|
+
|
25
|
+
def to_value = @v ||= Value.new(self)
|
26
|
+
|
27
|
+
def initialize(iterable, visibility:)
|
28
|
+
super(iterable.identifier(:range, abbreviate: visibility == :internal), visibility:)
|
29
|
+
dependencies << (@iterable = iterable) << INFO
|
30
|
+
end
|
31
|
+
|
32
|
+
def type_tag = "#{iterable.type_tag}::Range"
|
33
|
+
|
34
|
+
def brief = "@brief Range (iterator) for type #{iterable.type_tag}"
|
35
|
+
|
36
|
+
def render_type_description(stream)
|
37
|
+
stream << %{
|
38
|
+
/**
|
39
|
+
#{defgroup}
|
40
|
+
|
41
|
+
#{brief}
|
42
|
+
|
43
|
+
Range is means of traversing though the container contents in a sequential manner.
|
44
|
+
It is basically an extension of iterator.
|
45
|
+
|
46
|
+
It can be used the following way:
|
47
|
+
|
48
|
+
@code{.c}
|
49
|
+
for(#{signature} r = #{new}(&it); !#{empty}(&r); #{pop_front}(&r)) { ... }
|
50
|
+
@endcode
|
51
|
+
|
52
|
+
@see @ref Range
|
53
|
+
|
54
|
+
@since 2.0
|
55
|
+
*/
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
alias _iterable iterable # Use _iterable.() within method bodies as it is shadowed by the commonly used iterable function parameter
|
62
|
+
|
63
|
+
def configure
|
64
|
+
super
|
65
|
+
method(:void, :create, { range: lvalue, iterable: iterable.const_rvalue }, instance: :custom_create).configure do
|
66
|
+
header %{
|
67
|
+
@brief Create a new range for the specified iterable
|
68
|
+
|
69
|
+
@param[out] range range to be initialized
|
70
|
+
@param[in] iterable container to iterate over
|
71
|
+
|
72
|
+
This function creates a range to iterate over all iterable's elements.
|
73
|
+
|
74
|
+
@note Previous contents of `*range` is overwritten.
|
75
|
+
|
76
|
+
@see #{type.new}
|
77
|
+
|
78
|
+
@since 2.0
|
79
|
+
}
|
80
|
+
end
|
81
|
+
method(self, :new, { iterable: iterable.const_rvalue }).configure do
|
82
|
+
dependencies << custom_create
|
83
|
+
header %{
|
84
|
+
@brief Return new range iterator for the specified container
|
85
|
+
|
86
|
+
@param[in] iterable container to iterate over
|
87
|
+
@return new initialized range
|
88
|
+
|
89
|
+
This function returns a new range created by @ref #{type.custom_create}.
|
90
|
+
It is intended to be used within the ***for(;;)*** statement as follows
|
91
|
+
|
92
|
+
@code{.c}
|
93
|
+
for(#{type.signature} r = #{type.new}(&it); !#{type.empty}(&r); #{type.pop_front}(&r)) { ... }
|
94
|
+
@endcode
|
95
|
+
|
96
|
+
where `it` is the iterable to iterate over and `r` is a locally-scoped range bound to it.
|
97
|
+
|
98
|
+
@since 2.0
|
99
|
+
}
|
100
|
+
inline_code %{
|
101
|
+
#{type} r;
|
102
|
+
assert(iterable);
|
103
|
+
#{custom_create.(:r, iterable)};
|
104
|
+
return r;
|
105
|
+
}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end # Range
|
110
|
+
|
111
|
+
|
112
|
+
# @abstract
|
113
|
+
class InputRange < Range
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def configure
|
118
|
+
super
|
119
|
+
method(:int, :empty, { range: const_rvalue }).configure do
|
120
|
+
header %{
|
121
|
+
@brief Check for range emptiness
|
122
|
+
|
123
|
+
@param[in] range range to check
|
124
|
+
@return non-zero value if the range is not empty or zero value otherwise
|
125
|
+
|
126
|
+
An empty range is the range for which there are to accessible elements left.
|
127
|
+
This specifically means that any calls to the element retrieval and position change functions
|
128
|
+
(@ref #{type.take_front}, @ref #{type.view_front}, @ref #{type.pop_front} et al.) are invalid for empty ranges.
|
129
|
+
|
130
|
+
@since 2.0
|
131
|
+
}
|
132
|
+
end
|
133
|
+
method(:void, :pop_front, { range: rvalue }).configure do
|
134
|
+
header %{
|
135
|
+
@brief Advance front position to the next existing element
|
136
|
+
|
137
|
+
@param[in] range range to advance front position for
|
138
|
+
|
139
|
+
This function is used to get to the next element in the range.
|
140
|
+
|
141
|
+
@note Prior calling this function one must ensure that the range is not empty (see @ref #{type.empty}).
|
142
|
+
Advancing position of a range that is already empty results in undefined behaviour.
|
143
|
+
|
144
|
+
@since 2.0
|
145
|
+
}
|
146
|
+
end
|
147
|
+
method(iterable.element.const_lvalue, :view_front, { range: const_rvalue }).configure do
|
148
|
+
header %{
|
149
|
+
@brief Get a view of the front element
|
150
|
+
|
151
|
+
@param[in] range range to retrieve element from
|
152
|
+
@return a view of an element at the range's front position
|
153
|
+
|
154
|
+
This function is used to get a constant reference (in form of the C pointer) to the value contained in the iterable container at the range's front position.
|
155
|
+
Refer to @ref #{type.take_front} to get an independent copy of that element.
|
156
|
+
|
157
|
+
It is generally not safe to bypass the constness and to alter the value in place (although no one prevents to).
|
158
|
+
|
159
|
+
@note Range must not be empty (see @ref #{type.empty}).
|
160
|
+
|
161
|
+
@since 2.0
|
162
|
+
}
|
163
|
+
end
|
164
|
+
method(iterable.element, :take_front, { range: const_rvalue }, constraint:-> { iterable.element.copyable? }).configure do
|
165
|
+
dependencies << empty << view_front
|
166
|
+
inline_code %{
|
167
|
+
#{iterable.element} result;
|
168
|
+
#{iterable.element.const_lvalue} e;
|
169
|
+
assert(!#{empty.(range)});
|
170
|
+
e = #{view_front.(range)};
|
171
|
+
#{iterable.element.copy.(:result, '*e')};
|
172
|
+
return result;
|
173
|
+
}
|
174
|
+
header %{
|
175
|
+
@brief Get a copy of the front element
|
176
|
+
|
177
|
+
@param[in] range range to retrieve element from
|
178
|
+
@return a *copy* of element at the range's front position
|
179
|
+
|
180
|
+
This function is used to get a *copy* of the value contained in the iterable container at the range's front position.
|
181
|
+
Refer to @ref #{type.view_front} to get a view of the element without making an independent copy.
|
182
|
+
|
183
|
+
This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation).
|
184
|
+
|
185
|
+
@note Range must not be empty (see @ref #{type.empty}).
|
186
|
+
|
187
|
+
@since 2.0
|
188
|
+
}
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
end # InputRange
|
193
|
+
|
194
|
+
|
195
|
+
# @abstract
|
196
|
+
class ForwardRange < InputRange
|
197
|
+
|
198
|
+
def copyable? = true
|
199
|
+
|
200
|
+
private
|
201
|
+
|
202
|
+
def configure
|
203
|
+
super
|
204
|
+
copy.configure do
|
205
|
+
header %{
|
206
|
+
@brief Create a copy of the range state
|
207
|
+
|
208
|
+
@param[out] target range to be created
|
209
|
+
@param[in] source range to be cloned
|
210
|
+
|
211
|
+
This function is meant to an independent copy (a clone) of `*source` range in place of `*target`.
|
212
|
+
|
213
|
+
Previous contents of `*target` is overwritten.
|
214
|
+
|
215
|
+
@since 2.0
|
216
|
+
}
|
217
|
+
inline_code %{
|
218
|
+
assert(target);
|
219
|
+
assert(source);
|
220
|
+
*target = *source;
|
221
|
+
}
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
end # ForwardRange
|
226
|
+
|
227
|
+
|
228
|
+
# @abstract
|
229
|
+
class BidirectionalRange < ForwardRange
|
230
|
+
|
231
|
+
private
|
232
|
+
|
233
|
+
def configure
|
234
|
+
super
|
235
|
+
method(:void, :pop_back, { range: rvalue }).configure do
|
236
|
+
header %{
|
237
|
+
@brief Rewind back position to the previous existing element
|
238
|
+
|
239
|
+
@param[in] range range to rewind back position for
|
240
|
+
|
241
|
+
This function is used to get to the previous element in the range.
|
242
|
+
|
243
|
+
@note Prior calling this function one must ensure that the range is not empty (see @ref #{type.empty}).
|
244
|
+
Rewinding position of a range that is already empty results in undefined behaviour.
|
245
|
+
|
246
|
+
@since 2.0
|
247
|
+
}
|
248
|
+
end
|
249
|
+
method(iterable.element.const_lvalue, :view_back, { range: const_rvalue }).configure do
|
250
|
+
header %{
|
251
|
+
@brief Get a view of the back element
|
252
|
+
|
253
|
+
@param[in] range range to retrieve element from
|
254
|
+
@return a view of an element at the range's back position
|
255
|
+
|
256
|
+
This function is used to get a constant reference (in form of the C pointer) to the value contained in the iterable container at the range's back position.
|
257
|
+
Refer to @ref #{type.take_back} to get an independent copy of that element.
|
258
|
+
|
259
|
+
It is generally not safe to bypass the constness and to alter the value in place (although no one prevents to).
|
260
|
+
|
261
|
+
@note Range must not be empty (see @ref #{type.empty}).
|
262
|
+
|
263
|
+
@since 2.0
|
264
|
+
}
|
265
|
+
end
|
266
|
+
method(iterable.element, :take_back, { range: const_rvalue }, constraint:-> { iterable.element.copyable? }).configure do
|
267
|
+
dependencies << empty << view_back
|
268
|
+
inline_code %{
|
269
|
+
#{iterable.element} result;
|
270
|
+
#{iterable.element.const_lvalue} e;
|
271
|
+
assert(!#{empty.(range)});
|
272
|
+
e = #{view_back.(range)};
|
273
|
+
#{iterable.element.copy.(:result, '*e')};
|
274
|
+
return result;
|
275
|
+
}
|
276
|
+
header %{
|
277
|
+
@brief Get a copy of the back element
|
278
|
+
|
279
|
+
@param[in] range range to retrieve element from
|
280
|
+
@return a *copy* of element at the range's back position
|
281
|
+
|
282
|
+
This function is used to get a *copy* of the value contained in the iterable container at the range's front position.
|
283
|
+
Refer to @ref #{type.view_back} to get a view of the element without making an independent copy.
|
284
|
+
|
285
|
+
This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation).
|
286
|
+
|
287
|
+
@note Range must not be empty (see @ref #{type.empty}).
|
288
|
+
|
289
|
+
@since 2.0
|
290
|
+
}
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
end # BidirectionalRange
|
295
|
+
|
296
|
+
|
297
|
+
# @abstract
|
298
|
+
class DirectAccessRange < BidirectionalRange
|
299
|
+
|
300
|
+
private
|
301
|
+
|
302
|
+
def configure
|
303
|
+
super
|
304
|
+
method(:size_t, :size, { range: const_rvalue }).configure do
|
305
|
+
header %{
|
306
|
+
@brief Get a number of elements in the range
|
307
|
+
|
308
|
+
@param[in] range range to query
|
309
|
+
@return a number of elements
|
310
|
+
|
311
|
+
This function returns a number of elements between the range's front and back positions inclusively.
|
312
|
+
As a consequence, the result changes with every invocation of position change functions (@ref #{type.pop_front}, @ref #{type.pop_back}),
|
313
|
+
so be careful not to cache this value.
|
314
|
+
|
315
|
+
For empty range this function returns 0.
|
316
|
+
|
317
|
+
@since 2.0
|
318
|
+
}
|
319
|
+
end
|
320
|
+
method(:int, :check, { range: const_rvalue, index: :size_t.const_rvalue } ).configure do
|
321
|
+
dependencies << size
|
322
|
+
inline_code %{
|
323
|
+
assert(range);
|
324
|
+
return index < #{size.(range)};
|
325
|
+
}
|
326
|
+
header %{
|
327
|
+
@brief Validate specified range's index
|
328
|
+
|
329
|
+
@param[in] range range to query
|
330
|
+
@param[in] index index to verify
|
331
|
+
@return non-zero value if speicfied index is valid and zero value otherwise
|
332
|
+
|
333
|
+
This function performs the range's index validity check.
|
334
|
+
|
335
|
+
In any case, this function should be used for the index validation prior getting direct access to range's elements
|
336
|
+
with @ref #{type.get}, @ref #{type.view} etc. as these functions do not normally do it themselves for performance reasons.
|
337
|
+
|
338
|
+
@since 2.0
|
339
|
+
}
|
340
|
+
end
|
341
|
+
method(iterable.element.const_lvalue, :view, { range: const_rvalue, index: :size_t.const_rvalue }).configure do
|
342
|
+
header %{
|
343
|
+
@brief Get view of the specific element
|
344
|
+
|
345
|
+
@param[in] range range to view element from
|
346
|
+
@param[in] index position to access element at
|
347
|
+
@return a view of element at `index`
|
348
|
+
|
349
|
+
This function is used to get a constant reference (in form of the C pointer) to the value contained in the range at the specific position.
|
350
|
+
Refer to @ref #{type.get} to get a copy of the element.
|
351
|
+
|
352
|
+
@note The specified `index` is required to be within the [0, @ref #{type.size}) range.
|
353
|
+
|
354
|
+
@since 2.0
|
355
|
+
}
|
356
|
+
end
|
357
|
+
method(iterable.element, :get, { range: const_rvalue, index: :size_t.const_rvalue }, constraint:-> { iterable.element.copyable? }).configure do
|
358
|
+
dependencies << check << view
|
359
|
+
inline_code %{
|
360
|
+
#{iterable.element} r;
|
361
|
+
#{iterable.element.const_lvalue} e;
|
362
|
+
assert(#{check.(range, index)});
|
363
|
+
e = #{view.(range, index)};
|
364
|
+
#{iterable.element.copy.(:r, '*e')};
|
365
|
+
return r;
|
366
|
+
}
|
367
|
+
header %{
|
368
|
+
@brief Get a copy of the specific element
|
369
|
+
|
370
|
+
@param[in] range range to retrieve element from
|
371
|
+
@param[in] index position to view element at
|
372
|
+
@return a *copy* of element at `index`
|
373
|
+
|
374
|
+
This function is used to get a *copy* of the value contained in the range at the specific position.
|
375
|
+
Refer to @ref #{type.view} to get a view of the element without making an independent copy.
|
376
|
+
|
377
|
+
This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation).
|
378
|
+
|
379
|
+
@note The specified `position` is required to be within the [0, @ref #{type.size}) range.
|
380
|
+
|
381
|
+
@since 2.0
|
382
|
+
}
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
end # DirectAccessRange
|
387
|
+
|
388
|
+
|
389
|
+
# @abstract
|
390
|
+
class ContiguousRange < DirectAccessRange
|
391
|
+
|
392
|
+
def initialize(iterable, visibility: :public, parallel: nil)
|
393
|
+
super(iterable, visibility:)
|
394
|
+
@parallel = parallel
|
395
|
+
end
|
396
|
+
|
397
|
+
def render_interface(stream)
|
398
|
+
if public?
|
399
|
+
case @parallel
|
400
|
+
when nil
|
401
|
+
stream << %{
|
402
|
+
/**
|
403
|
+
#{defgroup}
|
404
|
+
|
405
|
+
#{brief}
|
406
|
+
|
407
|
+
This is the range for contiguous data structures (vectors, strings etc.)
|
408
|
+
|
409
|
+
It can be used the following way:
|
410
|
+
|
411
|
+
@code{.c}
|
412
|
+
for(#{signature} r = #{new}(&it); !#{empty}(&r); #{pop_front}(&r)) { ... }
|
413
|
+
@endcode
|
414
|
+
|
415
|
+
@see @ref Range
|
416
|
+
|
417
|
+
@since 2.0
|
418
|
+
*/
|
419
|
+
}
|
420
|
+
when :openmp
|
421
|
+
stream << %{
|
422
|
+
/**
|
423
|
+
#{defgroup}
|
424
|
+
|
425
|
+
#{brief}
|
426
|
+
|
427
|
+
This is the range for contiguous data structures (vectors, strings etc.)
|
428
|
+
|
429
|
+
The @ref #{new} and @ref #{custom_create} range constructors create OpenMP-aware range objects
|
430
|
+
which account for parallel iteration in the way
|
431
|
+
|
432
|
+
@code{.c}
|
433
|
+
#pragma omp parallel
|
434
|
+
for(#{signature} r = #{new}(&it); !#{empty}(&r); #{pop_front}(&r)) { ... }
|
435
|
+
@endcode
|
436
|
+
|
437
|
+
@see @ref Range
|
438
|
+
|
439
|
+
@since 2.0
|
440
|
+
*/
|
441
|
+
}
|
442
|
+
end
|
443
|
+
else
|
444
|
+
stream << PRIVATE
|
445
|
+
end
|
446
|
+
if public?
|
447
|
+
stream << %{
|
448
|
+
/**
|
449
|
+
#{ingroup}
|
450
|
+
@brief Opaque structure holding state of the contiguous container's range
|
451
|
+
@since 2.0
|
452
|
+
*/
|
453
|
+
}
|
454
|
+
else
|
455
|
+
stream << PRIVATE
|
456
|
+
end
|
457
|
+
stream << %{
|
458
|
+
typedef struct {
|
459
|
+
#{iterable.element.lvalue} front; /**< @private */
|
460
|
+
#{iterable.element.lvalue} back; /**< @private */
|
461
|
+
} #{signature};
|
462
|
+
}
|
463
|
+
end
|
464
|
+
|
465
|
+
private
|
466
|
+
|
467
|
+
OPTIONAL_OMP_H = AutoC::Code.new interface: %{
|
468
|
+
#ifdef _OPENMP
|
469
|
+
#include <omp.h>
|
470
|
+
#endif
|
471
|
+
}
|
472
|
+
|
473
|
+
def configure
|
474
|
+
super
|
475
|
+
case @parallel
|
476
|
+
when nil
|
477
|
+
custom_create.configure do
|
478
|
+
inline_code %{
|
479
|
+
assert(range);
|
480
|
+
assert(iterable);
|
481
|
+
range->front = #{_iterable.storage(iterable)};
|
482
|
+
range->back = #{_iterable.storage(iterable)} + #{_iterable.size.(iterable)} - 1;
|
483
|
+
}
|
484
|
+
end
|
485
|
+
when :openmp
|
486
|
+
dependencies << OPTIONAL_OMP_H
|
487
|
+
custom_create.configure do
|
488
|
+
inline_code %{
|
489
|
+
size_t size;
|
490
|
+
#ifdef _OPENMP
|
491
|
+
unsigned chunk_count;
|
492
|
+
#endif
|
493
|
+
assert(range);
|
494
|
+
assert(iterable);
|
495
|
+
size = #{_iterable.size.(iterable)};
|
496
|
+
#ifdef _OPENMP
|
497
|
+
if(omp_in_parallel() && (chunk_count = omp_get_num_threads()) > 1) {
|
498
|
+
int chunk_id = omp_get_thread_num();
|
499
|
+
size_t chunk_size = size / omp_get_num_threads();
|
500
|
+
range->front = #{_iterable.storage(iterable)} + chunk_id*chunk_size;
|
501
|
+
range->back = #{_iterable.storage(iterable)} + (
|
502
|
+
chunk_id < chunk_count - 1 ?
|
503
|
+
(chunk_id + 1)*chunk_size - 1 :
|
504
|
+
size - 1
|
505
|
+
);
|
506
|
+
} else {
|
507
|
+
#endif
|
508
|
+
range->front = #{_iterable.storage(iterable)};
|
509
|
+
range->back = #{_iterable.storage(iterable)} + size - 1;
|
510
|
+
#ifdef _OPENMP
|
511
|
+
}
|
512
|
+
#endif
|
513
|
+
}
|
514
|
+
end
|
515
|
+
else
|
516
|
+
raise "unsupported parallel range specifier #{@parallel}"
|
517
|
+
end
|
518
|
+
empty.configure do
|
519
|
+
inline_code %{
|
520
|
+
assert(range);
|
521
|
+
assert(range->front);
|
522
|
+
assert(range->back);
|
523
|
+
return range->front > range->back;
|
524
|
+
}
|
525
|
+
end
|
526
|
+
pop_front.configure do
|
527
|
+
dependencies << empty
|
528
|
+
inline_code %{
|
529
|
+
assert(range);
|
530
|
+
assert(range->front);
|
531
|
+
assert(!#{empty.(range)});
|
532
|
+
++range->front;
|
533
|
+
}
|
534
|
+
end
|
535
|
+
pop_back.configure do
|
536
|
+
dependencies << empty
|
537
|
+
inline_code %{
|
538
|
+
assert(range);
|
539
|
+
assert(range->back);
|
540
|
+
assert(!#{empty.(range)});
|
541
|
+
--range->back;
|
542
|
+
}
|
543
|
+
end
|
544
|
+
view_front.configure do
|
545
|
+
dependencies << empty
|
546
|
+
inline_code %{
|
547
|
+
assert(range);
|
548
|
+
assert(range->front);
|
549
|
+
assert(!#{empty.(range)});
|
550
|
+
return range->front;
|
551
|
+
}
|
552
|
+
end
|
553
|
+
view_back.configure do
|
554
|
+
dependencies << empty
|
555
|
+
inline_code %{
|
556
|
+
assert(range);
|
557
|
+
assert(range->back);
|
558
|
+
assert(!#{empty.(range)});
|
559
|
+
return range->back;
|
560
|
+
}
|
561
|
+
end
|
562
|
+
size.configure do
|
563
|
+
dependencies << empty
|
564
|
+
inline_code %{
|
565
|
+
assert(range);
|
566
|
+
assert(range->front);
|
567
|
+
assert(range->back);
|
568
|
+
return #{empty.(range)} ? 0 : range->back - range->front + 1;
|
569
|
+
}
|
570
|
+
end
|
571
|
+
view.configure do
|
572
|
+
dependencies << check
|
573
|
+
inline_code %{
|
574
|
+
assert(range);
|
575
|
+
assert(#{check.(range, index)});
|
576
|
+
return range->front + index;
|
577
|
+
}
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|
581
|
+
end # ContiguousRange
|
582
|
+
|
583
|
+
|
584
|
+
class AssociativeRange < ForwardRange
|
585
|
+
|
586
|
+
private
|
587
|
+
|
588
|
+
def configure
|
589
|
+
super
|
590
|
+
method(iterable.index.const_lvalue, :view_index_front, { range: const_rvalue }).configure do
|
591
|
+
header %{
|
592
|
+
@brief Get a view of the front index
|
593
|
+
|
594
|
+
@param[in] range range to retrieve element from
|
595
|
+
@return a view of an index at the range's front position
|
596
|
+
|
597
|
+
This function is used to get a constant reference (in form of the C pointer) to the index associated with element at the range's front position.
|
598
|
+
Refer to @ref #{type.take_index_front} to get an independent copy of that index.
|
599
|
+
|
600
|
+
It is generally not safe to bypass the constness and to alter the value in place (although no one prevents to).
|
601
|
+
|
602
|
+
@note Range must not be empty (see @ref #{type.empty}).
|
603
|
+
|
604
|
+
@since 2.0
|
605
|
+
}
|
606
|
+
end
|
607
|
+
method(iterable.index, :take_index_front, { range: const_rvalue }, constraint:-> { iterable.index.copyable? && iterable.element.copyable? }).configure do
|
608
|
+
dependencies << empty << view_index_front
|
609
|
+
inline_code %{
|
610
|
+
#{iterable.index} result;
|
611
|
+
#{iterable.index.const_lvalue} e;
|
612
|
+
assert(!#{empty.(range)});
|
613
|
+
e = #{view_index_front.(range)};
|
614
|
+
#{iterable.index.copy.(:result, '*e')};
|
615
|
+
return result;
|
616
|
+
}
|
617
|
+
header %{
|
618
|
+
@brief Get a copy of the front index associated with element
|
619
|
+
|
620
|
+
@param[in] range range to retrieve element from
|
621
|
+
@return a *copy* of index at the range's front position
|
622
|
+
|
623
|
+
This function is used to get a *copy* of the index associated with element at the range's front position.
|
624
|
+
Refer to @ref #{type.view_index_front} to get a view of the index without making an independent copy.
|
625
|
+
|
626
|
+
This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation).
|
627
|
+
|
628
|
+
@note Range must not be empty (see @ref #{type.empty}).
|
629
|
+
|
630
|
+
@since 2.0
|
631
|
+
}
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
635
|
+
end # AssociativeRange
|
636
|
+
|
637
|
+
|
638
|
+
Range::INFO = Code.new interface: %{
|
639
|
+
/**
|
640
|
+
@page Range
|
641
|
+
|
642
|
+
@brief Generalization of the iterator
|
643
|
+
|
644
|
+
A range is a means of traversing through the container's contents in which it is similar to the iterator.
|
645
|
+
|
646
|
+
Current implementation is loosely modeled after the [D language ranges](https://dlang.org/phobos/std_range.html).
|
647
|
+
|
648
|
+
Note that current ranges' implementation is fairly basic lacking iterable alteration, thread safety etc.
|
649
|
+
On the other hand, all currently implemented ranges are the simple value types which do not require explicit
|
650
|
+
copying/destruction thus making life slightly easier.
|
651
|
+
Therefore they can be passed out in/out the functions as is - just watch out the dangers of passing the
|
652
|
+
iterable values they are bound to.
|
653
|
+
|
654
|
+
A sample code involving iteration over the contents of a hypothetical `List` iterable value is shown below.
|
655
|
+
|
656
|
+
@code{.c}
|
657
|
+
List list;
|
658
|
+
...
|
659
|
+
for(ListRange r = ListRangeNew(&list); !ListRangeEmpty(&r); ListRangePopFront(&r)) {
|
660
|
+
... = ListRangeTakeFront(&r);
|
661
|
+
}
|
662
|
+
@endcode
|
663
|
+
|
664
|
+
Currently implemented range archetypes:
|
665
|
+
@subpage InputRange
|
666
|
+
@subpage ForwardRange
|
667
|
+
@subpage BidirectionalRange
|
668
|
+
@subpage DirectAccessRange
|
669
|
+
|
670
|
+
@since 2.0
|
671
|
+
|
672
|
+
@page InputRange
|
673
|
+
|
674
|
+
@brief Basic unidirectional range
|
675
|
+
|
676
|
+
An input range is a @ref Range which sports a single direction of traversing the elements.
|
677
|
+
|
678
|
+
@since 2.0
|
679
|
+
|
680
|
+
@page ForwardRange
|
681
|
+
|
682
|
+
@brief Unidirectional range with checkpoint
|
683
|
+
|
684
|
+
A forward range is an @ref InputRange which also allows to make a snapshot of the current range's state for possible fallback.
|
685
|
+
|
686
|
+
@since 2.0
|
687
|
+
|
688
|
+
@page BidirectionalRange
|
689
|
+
|
690
|
+
@brief Basic bidirectional range
|
691
|
+
|
692
|
+
A bidirectional range is a @ref ForwardRange which can also be traversed backwards.
|
693
|
+
|
694
|
+
@since 2.0
|
695
|
+
|
696
|
+
@page DirectAccessRange
|
697
|
+
|
698
|
+
@brief Bidirectional range with indexed access to specific elements
|
699
|
+
|
700
|
+
A random access range is a @ref BidirectionalRange which is also capable of accessing the elements directly using index.
|
701
|
+
|
702
|
+
@since 2.0
|
703
|
+
*/
|
704
|
+
}
|
705
|
+
|
706
|
+
|
707
|
+
end
|