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.
Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +3 -0
  3. data/README.md +149 -0
  4. data/cmake/AutoC.cmake +39 -0
  5. data/lib/autoc/allocators.rb +51 -0
  6. data/lib/autoc/association.rb +126 -0
  7. data/lib/autoc/box.rb +311 -0
  8. data/lib/autoc/cmake.rb +54 -0
  9. data/lib/autoc/collection.rb +83 -110
  10. data/lib/autoc/composite.rb +333 -0
  11. data/lib/autoc/cstring.rb +263 -0
  12. data/lib/autoc/function.rb +247 -0
  13. data/lib/autoc/hash_map.rb +328 -0
  14. data/lib/autoc/hash_set.rb +339 -0
  15. data/lib/autoc/hashers.rb +102 -0
  16. data/lib/autoc/list.rb +444 -0
  17. data/lib/autoc/module.rb +434 -0
  18. data/lib/autoc/openmp.rb +15 -0
  19. data/lib/autoc/primitive.rb +27 -0
  20. data/lib/autoc/ranges.rb +707 -0
  21. data/lib/autoc/record.rb +247 -0
  22. data/lib/autoc/scaffold/docs.rb +117 -0
  23. data/lib/autoc/scaffold/generic_value.rb +86 -0
  24. data/lib/autoc/scaffold/project.rb +75 -0
  25. data/lib/autoc/scaffold/test_cstring.rb +113 -0
  26. data/lib/autoc/scaffold/test_cstring_hash_set.rb +35 -0
  27. data/lib/autoc/scaffold/test_int_box.rb +22 -0
  28. data/lib/autoc/scaffold/test_int_hash_set.rb +448 -0
  29. data/lib/autoc/scaffold/test_int_list.rb +106 -0
  30. data/lib/autoc/scaffold/test_int_vector.rb +83 -0
  31. data/lib/autoc/scaffold/test_v2v_hash_map.rb +83 -0
  32. data/lib/autoc/scaffold/test_value_hash_set.rb +60 -0
  33. data/lib/autoc/scaffold/test_value_vector.rb +146 -0
  34. data/{test/test.rb → lib/autoc/scaffold/tests.rb} +179 -158
  35. data/lib/autoc/scaffold.rb +12 -0
  36. data/lib/autoc/sequential.rb +99 -0
  37. data/lib/autoc/set.rb +331 -0
  38. data/lib/autoc/std.rb +149 -0
  39. data/lib/autoc/type.rb +93 -531
  40. data/lib/autoc/vector.rb +290 -0
  41. data/lib/autoc.rb +4 -35
  42. metadata +55 -85
  43. data/.yardopts +0 -4
  44. data/CHANGES +0 -23
  45. data/README +0 -28
  46. data/doc/AutoC/Code.html +0 -523
  47. data/doc/AutoC/Collection.html +0 -1214
  48. data/doc/AutoC/HashMap.html +0 -1441
  49. data/doc/AutoC/HashSet.html +0 -916
  50. data/doc/AutoC/Iterators/Bidirectional.html +0 -204
  51. data/doc/AutoC/Iterators/Unidirectional.html +0 -200
  52. data/doc/AutoC/Iterators.html +0 -126
  53. data/doc/AutoC/List.html +0 -1039
  54. data/doc/AutoC/Maps.html +0 -290
  55. data/doc/AutoC/Module/File.html +0 -415
  56. data/doc/AutoC/Module/Header.html +0 -437
  57. data/doc/AutoC/Module/Source.html +0 -707
  58. data/doc/AutoC/Module.html +0 -948
  59. data/doc/AutoC/Priority.html +0 -138
  60. data/doc/AutoC/Queue.html +0 -1172
  61. data/doc/AutoC/Reference.html +0 -735
  62. data/doc/AutoC/Sets.html +0 -520
  63. data/doc/AutoC/String.html +0 -1394
  64. data/doc/AutoC/TreeMap.html +0 -1565
  65. data/doc/AutoC/TreeSet.html +0 -1447
  66. data/doc/AutoC/Type.html +0 -2148
  67. data/doc/AutoC/UserDefinedType.html +0 -1047
  68. data/doc/AutoC/Vector.html +0 -987
  69. data/doc/AutoC.html +0 -331
  70. data/doc/_index.html +0 -388
  71. data/doc/class_list.html +0 -51
  72. data/doc/css/common.css +0 -1
  73. data/doc/css/full_list.css +0 -58
  74. data/doc/css/style.css +0 -481
  75. data/doc/file.CHANGES.html +0 -117
  76. data/doc/file.README.html +0 -116
  77. data/doc/file_list.html +0 -61
  78. data/doc/frames.html +0 -17
  79. data/doc/index.html +0 -116
  80. data/doc/js/app.js +0 -243
  81. data/doc/js/full_list.js +0 -216
  82. data/doc/js/jquery.js +0 -4
  83. data/doc/method_list.html +0 -1307
  84. data/doc/top-level-namespace.html +0 -112
  85. data/lib/autoc/code.rb +0 -237
  86. data/lib/autoc/collection/hash_map.rb +0 -385
  87. data/lib/autoc/collection/hash_set.rb +0 -337
  88. data/lib/autoc/collection/iterator.rb +0 -39
  89. data/lib/autoc/collection/list.rb +0 -429
  90. data/lib/autoc/collection/map.rb +0 -41
  91. data/lib/autoc/collection/queue.rb +0 -517
  92. data/lib/autoc/collection/set.rb +0 -134
  93. data/lib/autoc/collection/tree_map.rb +0 -464
  94. data/lib/autoc/collection/tree_set.rb +0 -611
  95. data/lib/autoc/collection/vector.rb +0 -336
  96. data/lib/autoc/string.rb +0 -492
  97. data/test/test_auto.c +0 -7141
  98. data/test/test_auto.h +0 -753
  99. data/test/test_char_string.rb +0 -270
  100. data/test/test_int_list.rb +0 -35
  101. data/test/test_int_tree_set.rb +0 -111
  102. data/test/test_int_vector.rb +0 -34
  103. data/test/test_value_hash_map.rb +0 -162
  104. data/test/test_value_hash_set.rb +0 -173
  105. data/test/test_value_list.rb +0 -193
  106. data/test/test_value_queue.rb +0 -275
  107. data/test/test_value_tree_map.rb +0 -176
  108. data/test/test_value_tree_set.rb +0 -173
  109. data/test/test_value_vector.rb +0 -155
  110. data/test/value.rb +0 -80
@@ -0,0 +1,328 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ require 'autoc/record'
5
+ require 'autoc/hash_set'
6
+ require 'autoc/association'
7
+
8
+
9
+ module AutoC
10
+
11
+
12
+ using STD::Coercions
13
+
14
+
15
+ class HashMap < Association
16
+
17
+ def _range_class = Range
18
+
19
+ def _node_class = Record
20
+
21
+ def _set_class = HashMap::HashSet
22
+
23
+ def range = @range ||= _range_class.new(self, visibility: visibility)
24
+
25
+ def _node = @_node ||= _node_class.new(identifier(:_node, abbreviate: true), { index: index, element: element }, _master: self, visibility: :internal)
26
+
27
+ def _set = @_set ||= _set_class.new(identifier(:_set, set_operations: false, abbreviate: true), _node, _master: self, visibility: :internal)
28
+
29
+ def orderable? = _set.orderable?
30
+
31
+ def initialize(*args, **kws)
32
+ super
33
+ dependencies << _set
34
+ end
35
+
36
+ def render_interface(stream)
37
+ if public?
38
+ stream << %{
39
+ /**
40
+ #{defgroup}
41
+
42
+ @brief Unordered collection of elements of type #{element} associated with unique index of type #{index}.
43
+
44
+ For iteration over the set elements refer to @ref #{range}.
45
+
46
+ @see C++ [std::unordered_map<K,T>](https://en.cppreference.com/w/cpp/container/unordered_map)
47
+
48
+ @since 2.0
49
+ */
50
+ /**
51
+ #{ingroup}
52
+ @brief Opaque structure holding state of the hash map
53
+ @since 2.0
54
+ */
55
+ }
56
+ else
57
+ stream << PRIVATE
58
+ end
59
+ stream << %{
60
+ typedef struct {
61
+ #{_set} set; /**< @private */
62
+ } #{signature};
63
+ }
64
+ end
65
+
66
+ private
67
+
68
+ def configure
69
+ super
70
+ method(:int, :remove, { target: rvalue, index: index.const_rvalue }, constraint:-> { index.comparable? }).configure do
71
+ code %{
72
+ assert(target);
73
+ return #{_set._remove_index_node.('target->set', index)};
74
+ }
75
+ header %{
76
+ @brief Remove element associated with index
77
+
78
+ @param[in] target map to process
79
+ @param[in] index index to look for
80
+ @return non-zero value on successful removal and zero value otherwise
81
+
82
+ This function removes and destroys index and associated element if any.
83
+ The function returns zero value if `target` contains no such association.
84
+
85
+ @since 2.0
86
+ }
87
+ end
88
+ default_create.configure do
89
+ code %{
90
+ assert(target);
91
+ #{_set.default_create.('target->set')};
92
+ }
93
+ end
94
+ set.configure do
95
+ code %{
96
+ #{_node.lvalue} node;
97
+ assert(target);
98
+ assert(target);
99
+ node = #{_set._find_index_node.('target->set', index)};
100
+ if(node) {
101
+ #{_node.destroy.('*node') if _node.destructible?};
102
+ #{_node.custom_create.('*node', index, value)}; /* override node's contents in-place */
103
+ } else {
104
+ #{_node} node;
105
+ #{_set._slot.lvalue} s = (#{_set._slot.lvalue})#{_set._find_index_slot.('target->set', index)};
106
+ /* construct temporary node as POD value; actual copying will be performed by the list itself */
107
+ node.index = index;
108
+ node.element = value;
109
+ #{_set._slot.push_front.('*s', :node)};
110
+ ++target->set.size; /* bypassing set's element manipulation functions incurs manual size management */
111
+ }
112
+ }
113
+ end
114
+ destroy.configure do
115
+ code %{
116
+ assert(target);
117
+ #{_set.destroy.('target->set')};
118
+ }
119
+ end
120
+ copy.configure do
121
+ code %{
122
+ assert(target);
123
+ assert(source);
124
+ #{_set.copy.('target->set', 'source->set')};
125
+ }
126
+ end
127
+ equal.configure do
128
+ code %{
129
+ assert(left);
130
+ assert(right);
131
+ return #{_set.equal.('left->set', 'right->set')};
132
+ }
133
+ end
134
+ hash_code.configure do
135
+ code %{
136
+ assert(target);
137
+ return #{_set.hash_code.('target->set')};
138
+ }
139
+ end
140
+ empty.configure do
141
+ code %{
142
+ assert(target);
143
+ return #{_set.empty.('target->set')};
144
+ }
145
+ end
146
+ size.configure do
147
+ code %{
148
+ assert(target);
149
+ return #{_set.size.('target->set')};
150
+ }
151
+ end
152
+ contains.configure do
153
+ code %{
154
+ assert(target);
155
+ return #{find_first.(target, value)} != NULL;
156
+ }
157
+ end
158
+ check.configure do
159
+ code %{
160
+ assert(target);
161
+ return #{_set._find_index_node.('target->set', index)} != NULL;
162
+ }
163
+ end
164
+ view.configure do
165
+ code %{
166
+ #{_node.lvalue} node;
167
+ assert(target);
168
+ node = #{_set._find_index_node.('target->set', index)};
169
+ return node ? &node->element : NULL;
170
+ }
171
+ end
172
+ find_first.configure do
173
+ code %{
174
+ #{range} r;
175
+ assert(target);
176
+ for(r = #{range.new.(target)}; !#{range.empty.(:r)}; #{range.pop_front.(:r)}) {
177
+ #{element.const_lvalue} e = #{range.view_front.(:r)};
178
+ if(#{element.equal.('*e', value)}) return e;
179
+ }
180
+ return NULL;
181
+ }
182
+ end
183
+ end
184
+
185
+ end # HashMap
186
+
187
+
188
+ class HashMap::HashSet < HashSet
189
+
190
+ def _slot_class = HashMap::List
191
+
192
+ attr_reader :_index
193
+
194
+ def initialize(*args, **kws)
195
+ super
196
+ _map = _master # this set is a subcomponent of the map
197
+ @_index = _map.index
198
+ end
199
+
200
+ private
201
+
202
+ def configure
203
+ super
204
+ method(_slot.const_lvalue, :_find_index_slot, { target: const_rvalue, index: _index.const_rvalue }, visibility: :internal).configure do
205
+ # Find slot based on the index hash code only bypassing element
206
+ dependencies << _find_slot
207
+ inline_code _find_slot_hash(_index.hash_code.(index))
208
+ end
209
+ method(element.lvalue, :_find_index_node, { target: const_rvalue, index: _index.const_rvalue }, visibility: :internal).configure do
210
+ code %{
211
+ #{_slot._node_p} curr;
212
+ #{_slot._node_p} prev;
213
+ #{_slot.const_lvalue} s = #{_find_index_slot.(target, index)};
214
+ return #{_slot._find_index_node.('*s', index, :prev, :curr)} ? &curr->element : NULL;
215
+ }
216
+ end
217
+ method(:int, :_remove_index_node, { target: rvalue, index: _index.const_rvalue }, visibility: :internal).configure do
218
+ code %{
219
+ int c;
220
+ #{_slot.lvalue} s = (#{_slot.lvalue})#{_find_index_slot.(target, index)};
221
+ c = #{_slot._remove_index_node.('*s', index)};
222
+ if(c) --target->size;
223
+ return c;
224
+ }
225
+ end
226
+ end
227
+
228
+ end # HashSet
229
+
230
+
231
+ class HashMap::List < List
232
+
233
+ attr_reader :_index
234
+
235
+ def initialize(*args, **kws)
236
+ super
237
+ _map = _master._master # this list is a subcomponent of a set which is in turn a subcomponent of the map
238
+ @_index = _map.index
239
+ end
240
+
241
+ private
242
+
243
+ def configure
244
+ super
245
+ method(:int, :_find_index_node, { target: const_rvalue, index: _index.const_rvalue, prev_p: _node_pp, curr_p: _node_pp }, constraint:-> { _index.comparable? }).configure do
246
+ # Locate node satisfying default element equality condition, return this and previous nodes
247
+ code _locate_node_equal(_index.equal.('curr->element.index', index))
248
+ end
249
+ method(:int, :_remove_index_node, { target: rvalue, index: _index.const_rvalue }, constraint:-> { _index.comparable? }).configure do
250
+ code _remove_first(_find_index_node.(target, index, :prev, :curr))
251
+ end
252
+ end
253
+
254
+ end # List
255
+
256
+
257
+ class HashMap::Range < AssociativeRange
258
+
259
+ def render_interface(stream)
260
+ if public?
261
+ render_type_description(stream)
262
+ stream << %{
263
+ /**
264
+ #{ingroup}
265
+ @brief Opaque structure holding state of the hash map's range
266
+ @since 2.0
267
+ */
268
+ }
269
+ else
270
+ stream << PRIVATE
271
+ end
272
+ stream << %{
273
+ typedef struct {
274
+ #{_range} set; /**< @private */
275
+ } #{signature};
276
+ }
277
+ end
278
+
279
+ # @private
280
+ def _range = _iterable._set.range
281
+
282
+ private
283
+
284
+ def configure
285
+ super
286
+ method(iterable._node.const_lvalue, :_view_node, { range: const_rvalue }, inline: true, visibility: :internal).configure do
287
+ code %{
288
+ assert(!#{empty.(range)});
289
+ return #{_range.view_front.('range->set')};
290
+ }
291
+ end
292
+ custom_create.configure do
293
+ code %{
294
+ assert(range);
295
+ assert(iterable);
296
+ #{_range.default_create.('range->set', '&iterable->set')};
297
+ }
298
+ end
299
+ empty.configure do
300
+ code %{
301
+ assert(range);
302
+ return #{_range.empty.('range->set')};
303
+ }
304
+ end
305
+ pop_front.configure do
306
+ code %{
307
+ assert(range);
308
+ #{_range.pop_front.('range->set')};
309
+ }
310
+ end
311
+ view_front.configure do
312
+ code %{
313
+ assert(range);
314
+ return &#{_view_node.(range)}->element;
315
+ }
316
+ end
317
+ view_index_front.configure do
318
+ code %{
319
+ assert(range);
320
+ return &#{_view_node.(range)}->index;
321
+ }
322
+ end
323
+ end
324
+
325
+ end # Range
326
+
327
+
328
+ end
@@ -0,0 +1,339 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ require 'autoc/vector'
5
+ require 'autoc/list'
6
+ require 'autoc/set'
7
+
8
+
9
+ module AutoC
10
+
11
+
12
+ using STD::Coercions
13
+
14
+
15
+ class HashSet < Set
16
+
17
+ def _slot_class = List
18
+
19
+ def _bin_class = Vector
20
+
21
+ def range = @range ||= Range.new(self, visibility: visibility)
22
+
23
+ def _slot = @_slot ||= _slot_class.new(identifier(:_list, abbreviate: true), element, _master: self, maintain_size: false, visibility: :internal)
24
+
25
+ def _bin = @_bin ||= _bin_class.new(identifier(:_vector, abbreviate: true), _slot, _master: self, visibility: :internal)
26
+
27
+ def initialize(*args, **kws)
28
+ super
29
+ dependencies << _bin
30
+ end
31
+
32
+ def render_interface(stream)
33
+ if public?
34
+ stream << %{
35
+ /**
36
+ #{defgroup}
37
+
38
+ @brief Unordered collection of unique elements of type #{element}
39
+
40
+ For iteration over the set elements refer to @ref #{range}.
41
+
42
+ @see C++ [std::unordered_set<T>](https://en.cppreference.com/w/cpp/container/unordered_set)
43
+
44
+ @since 2.0
45
+ */
46
+ /**
47
+ #{ingroup}
48
+ @brief Opaque structure holding state of the hash set
49
+ @since 2.0
50
+ */
51
+ }
52
+ else
53
+ stream << PRIVATE
54
+ end
55
+ stream << %{
56
+ typedef struct {
57
+ #{_bin} bin; /**< @private */
58
+ size_t size; /**< @private */
59
+ size_t hash_mask; /**< @private */
60
+ } #{signature};
61
+ }
62
+ end
63
+
64
+ private
65
+
66
+ def configure
67
+ super
68
+ method(:void, :create_capacity, { target: lvalue, capacity: :size_t.rvalue }).configure do
69
+ code %{
70
+ unsigned char bits = 0;
71
+ assert(target);
72
+ target->size = 0;
73
+ /* fix capacity to become the ceiling to the nearest power of two */
74
+ if(capacity % 2 == 0) --capacity;
75
+ while(capacity >>= 1) ++bits;
76
+ capacity = (size_t)1 << (bits+1); assert(capacity > 0);
77
+ target->hash_mask = capacity-1; /* fast slot location for value: hash_code(value) & hash_mask */
78
+ #{_bin.custom_create.('target->bin', capacity)};
79
+ assert(#{_bin.size.('target->bin')} % 2 == 0);
80
+ }
81
+ header %{
82
+ @brief Create set with specified capacity
83
+
84
+ @param[out] target set to create
85
+ @param[in] capacity initial capacity of the set
86
+
87
+ This function creates a new set which should be suffice to contain specific number of elements.
88
+
89
+ While the input capacity may be arbitrary the resulting one will be rounded up to the nearest power of two.
90
+
91
+ This function may be useful when the (approximate) number of elements this set is about to contain is known in advance
92
+ in order to avoid expensive storage reallocation & elements rehashing operations during the set's lifetime.
93
+
94
+ @since 2.0
95
+ }
96
+ end
97
+ def _find_slot_hash(hash)
98
+ %{
99
+ assert(target);
100
+ return #{_bin.view.('target->bin', "#{hash} & target->hash_mask")};
101
+ }
102
+ end
103
+ method(_slot.const_lvalue, :_find_slot, { target: const_rvalue, value: element.const_rvalue }, visibility: :internal).configure do
104
+ # Find slot based on the value hash code
105
+ dependencies << _bin.view
106
+ inline_code _find_slot_hash(element.hash_code.(value))
107
+ end
108
+ method(:void, :_expand, { target: lvalue, force: :int.const_rvalue }, visibility: :internal).configure do
109
+ code %{
110
+ #{type} set;
111
+ #{_bin.range} r;
112
+ assert(target);
113
+ /* capacity threshold == 1.0 */
114
+ if(force || target->size >= #{_bin.size.('target->bin')}) {
115
+ #{create_capacity.(:set, _bin.size.('target->bin') + '*2')};
116
+ /* move elements to newly allocated set */
117
+ for(r = #{_bin.range.new.('target->bin')}; !#{_bin.range.empty.(:r)}; #{_bin.range.pop_front.(:r)}) {
118
+ #{_slot.lvalue} src = (#{_slot.lvalue})#{_bin.range.view_front.(:r)};
119
+ while(!#{_slot.empty.('*src')}) {
120
+ /* direct node relocation from original to new list bypassing node reallocation & payload copying */
121
+ #{_slot._node_p} node = #{_slot._pull_node.('*src')};
122
+ #{_slot.lvalue} dst = (#{_slot.lvalue})#{_find_slot.(target, 'node->element')};
123
+ #{_slot._push_node.('*dst', '*node')};
124
+ }
125
+ }
126
+ set.size = target->size; /* assume all elements have been moved into new set */
127
+ #{destroy.(target)};
128
+ *target = set;
129
+ }
130
+ }
131
+ end
132
+ subset.configure do
133
+ code %{
134
+ #{range} r;
135
+ assert(target);
136
+ assert(other);
137
+ if(#{size.(target)} > #{size.(other)}) return 0; /* larger set can't be a subset of a smaller one */
138
+ for(r = #{range.new.(target)}; !#{range.empty.(:r)}; #{range.pop_front.(:r)}) {
139
+ #{element.const_lvalue} e = #{range.view_front.(:r)};
140
+ if(!#{contains.(other, '*e')}) return 0;
141
+ }
142
+ return 1;
143
+ }
144
+ end
145
+ remove.configure do
146
+ code %{
147
+ int c;
148
+ #{_slot.lvalue} s;
149
+ assert(target);
150
+ s = (#{_slot.lvalue})#{_find_slot.(target, value)};
151
+ c = #{_slot.remove_first.('*s', value)};
152
+ if(c) --target->size;
153
+ return c;
154
+ }
155
+ end
156
+ put.configure do
157
+ code %{
158
+ #{_slot.lvalue} s;
159
+ assert(target);
160
+ s = (#{_slot.lvalue})#{_find_slot.(target, value)};
161
+ if(!#{_slot.find_first.('*s', value)}) {
162
+ #{_expand.(target, 0)};
163
+ #{_slot.push_front.('*s', value)};
164
+ ++target->size;
165
+ return 1;
166
+ } else return 0;
167
+ }
168
+ end
169
+ push.configure do
170
+ code %{
171
+ #{_slot.lvalue} s;
172
+ assert(target);
173
+ s = (#{_slot.lvalue})#{_find_slot.(target, value)};
174
+ if(#{_slot._replace_first.('*s', value)}) {
175
+ return 1;
176
+ } else {
177
+ /* add brand new value */
178
+ #{_expand.(target, 0)};
179
+ #{_slot.push_front.('*s', value)};
180
+ ++target->size;
181
+ return 0;
182
+ }
183
+ }
184
+ end
185
+ default_create.configure do
186
+ dependencies << create_capacity
187
+ inline_code %{
188
+ #{create_capacity.(target, 8)};
189
+ }
190
+ end
191
+ find_first.configure do
192
+ code %{
193
+ #{_slot.const_lvalue} s = #{_find_slot.(target, value)};
194
+ return #{_slot.find_first.('*s', value)};
195
+ }
196
+ end
197
+ copy.configure do
198
+ code %{
199
+ assert(target);
200
+ assert(source);
201
+ #{_bin.copy.('target->bin', 'source->bin')};
202
+ target->hash_mask = source->hash_mask;
203
+ target->size = source->size;
204
+ }
205
+ end
206
+ empty.configure do
207
+ inline_code %{
208
+ assert(target);
209
+ return target->size == 0;
210
+ }
211
+ end
212
+ size.configure do
213
+ inline_code %{
214
+ assert(target);
215
+ return target->size;
216
+ }
217
+ end
218
+ contains.configure do
219
+ code %{
220
+ #{_slot.const_lvalue} s;
221
+ assert(target);
222
+ s = #{_find_slot.(target, value)};
223
+ return #{_slot.contains.('*s', value)};
224
+ }
225
+ end
226
+ destroy.configure do
227
+ code %{
228
+ assert(target);
229
+ #{_bin.destroy.('target->bin')};
230
+ }
231
+ end
232
+ hash_code.configure do
233
+ code %{
234
+ #{range} r;
235
+ size_t hash;
236
+ for(hash = AUTOC_HASHER_SEED, r = #{range.new.(target)}; !#{range.empty.(:r)}; #{range.pop_front.(:r)}) {
237
+ #{element.const_lvalue} e = #{range.view_front.(:r)};
238
+ hash ^= #{element.hash_code.('*e')}; /* default incremental hasher is applicable to ordered collections only */
239
+ }
240
+ return hash;
241
+ }
242
+ end
243
+ end
244
+
245
+ end # HashSet
246
+
247
+
248
+ class HashSet::Range < ForwardRange
249
+
250
+ def render_interface(stream)
251
+ if public?
252
+ render_type_description(stream)
253
+ stream << %{
254
+ /**
255
+ #{ingroup}
256
+ @brief Opaque structure holding state of the hash set's range
257
+ @since 2.0
258
+ */
259
+ }
260
+ else
261
+ stream << PRIVATE
262
+ end
263
+ stream << %{
264
+ typedef struct {
265
+ #{_bin} bin; /**< @private */
266
+ #{_slot} slot; /**< @private */
267
+ } #{signature};
268
+ }
269
+ end
270
+
271
+ def _slot = iterable._slot.range
272
+
273
+ def _bin = iterable._bin.range
274
+
275
+ private
276
+
277
+ def configure
278
+ super
279
+ method(:void, :_advance, { range: rvalue }, visibility: :internal ).configure do
280
+ code %{
281
+ assert(range);
282
+ while(1) {
283
+ if(#{_slot.empty.('range->slot')}) {
284
+ /* current slot's range is empty - iterate forward to the next one */
285
+ #{_bin.pop_front.('range->bin')};
286
+ if(#{_bin.empty.('range->bin')}) {
287
+ /* all bin are iterated through, slot range is also empty - end of set */
288
+ break;
289
+ } else {
290
+ /* advance to the new (possibly empty) slot */
291
+ #{iterable._slot.const_lvalue} b = #{_bin.view_front.('range->bin')};
292
+ range->slot = #{_slot.new.('*b')};
293
+ }
294
+ } else {
295
+ /* current slot's range is not empty - no need to proceed */
296
+ break;
297
+ }
298
+ }
299
+ }
300
+ end
301
+ custom_create.configure do
302
+ code %{
303
+ #{_iterable._slot.const_lvalue} s;
304
+ assert(range);
305
+ assert(iterable);
306
+ range->bin = #{_bin.new.('iterable->bin')};
307
+ /* get the first slot's range regardless of its emptiness status */
308
+ s = #{_bin.view_front.('range->bin')};
309
+ range->slot = #{_slot.new.('*s')};
310
+ /* actually advance to the first non-empty slot */
311
+ #{_advance.(range)};
312
+ }
313
+ end
314
+ empty.configure do
315
+ code %{
316
+ assert(range);
317
+ return #{_slot.empty.('range->slot')};
318
+ }
319
+ end
320
+ pop_front.configure do
321
+ code %{
322
+ assert(range);
323
+ #{_slot.pop_front.('range->slot')};
324
+ #{_advance.(range)};
325
+ }
326
+ end
327
+ view_front.configure do
328
+ code %{
329
+ assert(range);
330
+ assert(!#{empty.(range)});
331
+ return #{_slot.view_front.('range->slot')};
332
+ }
333
+ end
334
+ end
335
+
336
+ end # Range
337
+
338
+
339
+ end