autoc 0.8 → 1.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 +7 -0
- data/README +15 -4
- data/doc/AutoC.html +245 -0
- data/doc/AutoC/Code.html +520 -0
- data/doc/AutoC/Collection.html +923 -0
- data/doc/AutoC/HashMap.html +1161 -0
- data/doc/AutoC/HashSet.html +1122 -0
- data/doc/AutoC/List.html +1002 -0
- data/doc/AutoC/Module.html +951 -0
- data/doc/AutoC/Module/File.html +412 -0
- data/doc/AutoC/Module/Header.html +432 -0
- data/doc/AutoC/Module/Source.html +704 -0
- data/doc/AutoC/Priority.html +138 -0
- data/doc/AutoC/Queue.html +1167 -0
- data/doc/AutoC/Type.html +1152 -0
- data/doc/AutoC/UserDefinedType.html +655 -0
- data/doc/AutoC/Vector.html +856 -0
- data/doc/_index.html +299 -0
- data/doc/class_list.html +54 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +339 -0
- data/doc/file.README.html +112 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +26 -0
- data/doc/index.html +112 -0
- data/doc/js/app.js +219 -0
- data/doc/js/full_list.js +178 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +605 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/autoc.rb +35 -12
- data/lib/autoc/{code_builder.rb → code.rb} +230 -247
- data/lib/autoc/collection.rb +137 -0
- data/lib/autoc/collection/hash_map.rb +388 -0
- data/lib/autoc/collection/hash_set.rb +433 -0
- data/lib/autoc/collection/list.rb +410 -0
- data/lib/autoc/collection/queue.rb +514 -0
- data/lib/autoc/collection/vector.rb +295 -0
- data/lib/autoc/type.rb +198 -0
- data/test/test.c +921 -396
- data/test/test.h +41 -0
- data/test/test.rb +21 -26
- data/test/test_auto.c +2630 -3961
- data/test/test_auto.h +449 -560
- metadata +50 -17
- data/lib/autoc/data_struct_builder.rb +0 -1794
- data/lib/autoc/type_builder.rb +0 -24
- data/manual/manual.pdf +0 -0
@@ -0,0 +1,433 @@
|
|
1
|
+
require "autoc/collection"
|
2
|
+
require "autoc/collection/list"
|
3
|
+
|
4
|
+
|
5
|
+
module AutoC
|
6
|
+
|
7
|
+
|
8
|
+
=begin
|
9
|
+
|
10
|
+
HashSet is a hash-based unordered container holding unique elements.
|
11
|
+
|
12
|
+
The collection's C++ counterpart is +std::unordered_set<>+ template class.
|
13
|
+
|
14
|
+
== Generated C interface
|
15
|
+
|
16
|
+
=== Collection management
|
17
|
+
|
18
|
+
[cols=2*]
|
19
|
+
|===
|
20
|
+
|*_void_* ~type~Copy(*_Type_* * +dst+, *_Type_* * +src+)
|
21
|
+
|
|
22
|
+
Create a new set +dst+ filled with the contents of +src+.
|
23
|
+
A copy operation is performed on every element in +src+.
|
24
|
+
|
25
|
+
NOTE: Previous contents of +dst+ is overwritten.
|
26
|
+
|
27
|
+
|*_void_* ~type~Ctor(*_Type_* * +self+)
|
28
|
+
|
|
29
|
+
Create a new empty set +self+.
|
30
|
+
|
31
|
+
NOTE: Previous contents of +self+ is overwritten.
|
32
|
+
|
33
|
+
|*_void_* ~type~Dtor(*_Type_* * +self+)
|
34
|
+
|
|
35
|
+
Destroy set +self+.
|
36
|
+
Stored elements are destroyed as well by calling the respective destructors.
|
37
|
+
|
38
|
+
|*_int_* ~type~Equal(*_Type_* * +lt+, *_Type_* * +rt+)
|
39
|
+
|
|
40
|
+
Return non-zero value if sets +lt+ and +rt+ are considered equal by contents and zero value otherwise.
|
41
|
+
|
42
|
+
|*_size_t_* ~type~Identify(*_Type_* * +self+)
|
43
|
+
|
|
44
|
+
Return hash code for set +self+.
|
45
|
+
|===
|
46
|
+
|
47
|
+
=== Basic operations
|
48
|
+
|
49
|
+
[cols=2*]
|
50
|
+
|===
|
51
|
+
|*_int_* ~type~Contains(*_Type_* * +self+, *_E_* +what+)
|
52
|
+
|
|
53
|
+
Return non-zero value if set +self+ contains an element considered equal to the element +what+ and zero value otherwise.
|
54
|
+
|
55
|
+
|*_int_* ~type~Empty(*_Type_* * +self+)
|
56
|
+
|
|
57
|
+
Return non-zero value if set +self+ contains no elements and zero value otherwise.
|
58
|
+
|
59
|
+
|*_E_* ~type~Get(*_Type_* * +self+, *_E_* +what+)
|
60
|
+
|
|
61
|
+
Return a _copy_ of the element in +self+ considered equal to the element +what+.
|
62
|
+
|
63
|
+
WARNING: +self+ *must* contain such element otherwise the behavior is undefined. See ~type~Contains().
|
64
|
+
|
65
|
+
|*_void_* ~type~Purge(*_Type_* * +self+)
|
66
|
+
|
|
67
|
+
Remove and destroy all elements stored in +self+.
|
68
|
+
|
69
|
+
|*_int_* ~type~Put(*_Type_* * +self+, *_E_* +what+)
|
70
|
+
|
|
71
|
+
Put a _copy_ of the element +what+ into +self+ *only if* there is no such element in +self+ which is considered equal to +what+.
|
72
|
+
|
73
|
+
Return non-zero value on successful element put and zero value otherwise.
|
74
|
+
|
75
|
+
|*_int_* ~type~Replace(*_Type_* * +self+, *_E_* +with+)
|
76
|
+
|
|
77
|
+
*If* +self+ contains an element which is considered equal to the element +with+,
|
78
|
+
replace that element with a _copy_ of +with+, otherwise do nothing.
|
79
|
+
Replaced element is destroyed.
|
80
|
+
|
81
|
+
Return non-zero value if the replacement was actually performed and zero value otherwise.
|
82
|
+
|
83
|
+
|*_int_* ~type~Remove(*_Type_* * +self+, *_E_* +what+)
|
84
|
+
|
|
85
|
+
Remove and destroy an element in +self+ which is considered equal to the element +what+.
|
86
|
+
|
87
|
+
Return non-zero value on successful element removal and zero value otherwise.
|
88
|
+
|
89
|
+
|*_size_t_* ~type~Size(*_Type_* * +self+)
|
90
|
+
|
|
91
|
+
Return number of elements stored in +self+.
|
92
|
+
|===
|
93
|
+
|
94
|
+
=== Logical operations
|
95
|
+
|
96
|
+
[cols=2*]
|
97
|
+
|===
|
98
|
+
|*_void_* ~type~Exclude(*_Type_* * +self+, *_Type_* * +other+)
|
99
|
+
|
|
100
|
+
Perform the difference operation that is +self+ will retain only the elements not contained in +other+.
|
101
|
+
|
102
|
+
Removed elements are destroyed.
|
103
|
+
|*_void_* ~type~Include(*_Type_* * +self+, *_Type_* * +other+)
|
104
|
+
|
|
105
|
+
Perform the union operation that is +self+ will contain the elements from both +self+ and +other+.
|
106
|
+
|
107
|
+
+self+ receives the _copies_ of extra elements in +other+.
|
108
|
+
|
109
|
+
|*_void_* ~type~Invert(*_Type_* * +self+, *_Type_* * +other+)
|
110
|
+
|
|
111
|
+
Perform the symmetric difference operation that is +self+ will retain the elements contained in either +self+ or +other+, but not in both.
|
112
|
+
|
113
|
+
Removed elements are destroyed, extra elements are _copied_.
|
114
|
+
|
115
|
+
|*_void_* ~type~Retain(*_Type_* * +self+, *_Type_* * +other+)
|
116
|
+
|
|
117
|
+
Perform the intersection operation that is +self+ will retain only the elements contained in both +self+ and +other+.
|
118
|
+
|
119
|
+
Removed elements are destroyed.
|
120
|
+
|===
|
121
|
+
|
122
|
+
=== Iteration
|
123
|
+
|
124
|
+
[cols=2*]
|
125
|
+
|===
|
126
|
+
|*_void_* ~it~Ctor(*_IteratorType_* * +it+, *_Type_* * +self+)
|
127
|
+
|
|
128
|
+
Create a new iterator +it+ on set +self+.
|
129
|
+
|
130
|
+
NOTE: As the set is an unordered sequence, the traversal order is unspecified.
|
131
|
+
|
132
|
+
NOTE: Previous contents of +it+ is overwritten.
|
133
|
+
|
134
|
+
|*_int_* ~it~Move(*_IteratorType_* * +it+)
|
135
|
+
|
|
136
|
+
Advance iterator position of +it+ *and* return non-zero value if new position is valid and zero value otherwise.
|
137
|
+
|
138
|
+
|*_E_* ~it~Get(*_IteratorType_* * +it+)
|
139
|
+
|
|
140
|
+
Return a _copy_ of current element pointed to by the iterator +it+.
|
141
|
+
|
142
|
+
WARNING: current position *must* be valid otherwise the behavior is undefined. See ~it~Move().
|
143
|
+
|===
|
144
|
+
|
145
|
+
=end
|
146
|
+
class HashSet < Collection
|
147
|
+
|
148
|
+
def initialize(*args)
|
149
|
+
super
|
150
|
+
@list = List.new(list, element, :static)
|
151
|
+
end
|
152
|
+
|
153
|
+
def write_exported_types(stream)
|
154
|
+
stream << %$
|
155
|
+
/***
|
156
|
+
**** #{type}<#{element.type}> (#{self.class})
|
157
|
+
***/
|
158
|
+
$ if public?
|
159
|
+
@list.write_exported_types(stream)
|
160
|
+
stream << %$
|
161
|
+
typedef struct #{type} #{type};
|
162
|
+
typedef struct #{it} #{it};
|
163
|
+
struct #{type} {
|
164
|
+
#{@list.type}* buckets;
|
165
|
+
size_t bucket_count, min_bucket_count;
|
166
|
+
size_t size, min_size, max_size;
|
167
|
+
unsigned min_fill, max_fill, capacity_multiplier; /* ?*1e-2 */
|
168
|
+
};
|
169
|
+
struct #{it} {
|
170
|
+
#{type}* set;
|
171
|
+
int bucket_index;
|
172
|
+
#{@list.it} it;
|
173
|
+
};
|
174
|
+
$
|
175
|
+
end
|
176
|
+
|
177
|
+
def write_exported_declarations(stream, declare, define)
|
178
|
+
stream << %$
|
179
|
+
#{declare} void #{ctor}(#{type}*);
|
180
|
+
#{declare} void #{dtor}(#{type}*);
|
181
|
+
#{declare} void #{copy}(#{type}*, #{type}*);
|
182
|
+
#{declare} int #{equal}(#{type}*, #{type}*);
|
183
|
+
#{declare} size_t #{identify}(#{type}*);
|
184
|
+
#{declare} void #{purge}(#{type}*);
|
185
|
+
#{declare} int #{contains}(#{type}*, #{element.type});
|
186
|
+
#{declare} #{element.type} #{get}(#{type}*, #{element.type});
|
187
|
+
#{declare} size_t #{size}(#{type}*);
|
188
|
+
#define #{empty}(self) (#{size}(self) == 0)
|
189
|
+
#{declare} int #{put}(#{type}*, #{element.type});
|
190
|
+
#{declare} int #{replace}(#{type}*, #{element.type});
|
191
|
+
#{declare} int #{remove}(#{type}*, #{element.type});
|
192
|
+
#{declare} void #{exclude}(#{type}*, #{type}*);
|
193
|
+
#{declare} void #{retain}(#{type}*, #{type}*);
|
194
|
+
#{declare} void #{include}(#{type}*, #{type}*);
|
195
|
+
#{declare} void #{invert}(#{type}*, #{type}*);
|
196
|
+
#{declare} void #{itCtor}(#{it}*, #{type}*);
|
197
|
+
#{declare} int #{itMove}(#{it}*);
|
198
|
+
#{declare} #{element.type} #{itGet}(#{it}*);
|
199
|
+
$
|
200
|
+
end
|
201
|
+
|
202
|
+
def write_implementations(stream, define)
|
203
|
+
@list.write_exported_declarations(stream, static, inline)
|
204
|
+
@list.write_implementations(stream, static)
|
205
|
+
stream << %$
|
206
|
+
#{define} #{element.type}* #{itGetRef}(#{it}*);
|
207
|
+
static void #{rehash}(#{type}* self) {
|
208
|
+
#{@list.type}* buckets;
|
209
|
+
size_t index, bucket_count, size, fill;
|
210
|
+
#{assert}(self);
|
211
|
+
#{assert}(self->min_fill > 0);
|
212
|
+
#{assert}(self->max_fill > 0);
|
213
|
+
#{assert}(self->min_fill < self->max_fill);
|
214
|
+
#{assert}(self->min_bucket_count > 0);
|
215
|
+
if(self->buckets) {
|
216
|
+
if(self->min_size < self->size && self->size < self->max_size) return;
|
217
|
+
fill = (size_t)((float)self->size/self->bucket_count*100);
|
218
|
+
if(fill > self->max_fill) {
|
219
|
+
bucket_count = (size_t)((float)self->bucket_count/100*self->capacity_multiplier);
|
220
|
+
} else
|
221
|
+
if(fill < self->min_fill && self->bucket_count > self->min_bucket_count) {
|
222
|
+
bucket_count = (size_t)((float)self->bucket_count/self->capacity_multiplier*100);
|
223
|
+
if(bucket_count < self->min_bucket_count) bucket_count = self->min_bucket_count;
|
224
|
+
} else
|
225
|
+
return;
|
226
|
+
size = self->size;
|
227
|
+
self->min_size = (size_t)((float)self->min_fill/100*size);
|
228
|
+
self->max_size = (size_t)((float)self->max_fill/100*size);
|
229
|
+
} else {
|
230
|
+
bucket_count = self->min_bucket_count;
|
231
|
+
size = 0;
|
232
|
+
}
|
233
|
+
buckets = (#{@list.type}*)#{malloc}(bucket_count*sizeof(#{@list.type})); #{assert}(buckets);
|
234
|
+
for(index = 0; index < bucket_count; ++index) {
|
235
|
+
#{@list.ctor}(&buckets[index]);
|
236
|
+
}
|
237
|
+
if(self->buckets) {
|
238
|
+
#{it} it;
|
239
|
+
#{itCtor}(&it, self);
|
240
|
+
while(#{itMove}(&it)) {
|
241
|
+
#{@list.type}* bucket;
|
242
|
+
#{element.type} element = #{itGet}(&it);
|
243
|
+
bucket = &buckets[#{element.identify("element")} % bucket_count];
|
244
|
+
#{@list.push}(bucket, element);
|
245
|
+
#{element.dtor("element")};
|
246
|
+
}
|
247
|
+
#{dtor}(self);
|
248
|
+
}
|
249
|
+
self->buckets = buckets;
|
250
|
+
self->bucket_count = bucket_count;
|
251
|
+
self->size = size;
|
252
|
+
}
|
253
|
+
#{define} void #{ctor}(#{type}* self) {
|
254
|
+
#{assert}(self);
|
255
|
+
self->min_bucket_count = 16;
|
256
|
+
self->min_fill = 20;
|
257
|
+
self->max_fill = 80;
|
258
|
+
self->min_size = (size_t)((float)self->min_fill/100*self->min_bucket_count);
|
259
|
+
self->max_size = (size_t)((float)self->max_fill/100*self->min_bucket_count);
|
260
|
+
self->capacity_multiplier = 200;
|
261
|
+
self->buckets = NULL;
|
262
|
+
#{rehash}(self);
|
263
|
+
}
|
264
|
+
#{define} void #{dtor}(#{type}* self) {
|
265
|
+
size_t i;
|
266
|
+
#{assert}(self);
|
267
|
+
for(i = 0; i < self->bucket_count; ++i) {
|
268
|
+
#{@list.dtor}(&self->buckets[i]);
|
269
|
+
}
|
270
|
+
#{free}(self->buckets);
|
271
|
+
}
|
272
|
+
#{define} void #{copy}(#{type}* dst, #{type}* src) {
|
273
|
+
#{it} it;
|
274
|
+
#{assert}(src);
|
275
|
+
#{assert}(dst);
|
276
|
+
#{ctor}(dst);
|
277
|
+
#{itCtor}(&it, src);
|
278
|
+
while(#{itMove}(&it)) #{put}(dst, *#{itGetRef}(&it));
|
279
|
+
}
|
280
|
+
static int #{containsAllOf}(#{type}* self, #{type}* other) {
|
281
|
+
#{it} it;
|
282
|
+
#{itCtor}(&it, self);
|
283
|
+
while(#{itMove}(&it)) {
|
284
|
+
int found = 0;
|
285
|
+
if(#{contains}(other, *#{itGetRef}(&it))) found = 1;
|
286
|
+
if(!found) return 0;
|
287
|
+
}
|
288
|
+
return 1;
|
289
|
+
}
|
290
|
+
#{define} int #{equal}(#{type}* lt, #{type}* rt) {
|
291
|
+
#{assert}(lt);
|
292
|
+
#{assert}(rt);
|
293
|
+
return #{size}(lt) == #{size}(rt) && #{containsAllOf}(lt, rt) && #{containsAllOf}(rt, lt);
|
294
|
+
}
|
295
|
+
#{define} size_t #{identify}(#{type}* self) {
|
296
|
+
#{it} it;
|
297
|
+
size_t result = 0;
|
298
|
+
#{assert}(self);
|
299
|
+
#{itCtor}(&it, self);
|
300
|
+
while(#{itMove}(&it)) {
|
301
|
+
#{element.type}* e = #{itGetRef}(&it);
|
302
|
+
result ^= #{element.identify("*e")};
|
303
|
+
result = AUTOC_RCYCLE(result);
|
304
|
+
}
|
305
|
+
return result;
|
306
|
+
}
|
307
|
+
#{define} void #{purge}(#{type}* self) {
|
308
|
+
#{assert}(self);
|
309
|
+
#{dtor}(self);
|
310
|
+
self->buckets = NULL;
|
311
|
+
#{rehash}(self);
|
312
|
+
}
|
313
|
+
#{define} int #{contains}(#{type}* self, #{element.type} element) {
|
314
|
+
#{assert}(self);
|
315
|
+
return #{@list.contains}(&self->buckets[#{element.identify("element")} % self->bucket_count], element);
|
316
|
+
}
|
317
|
+
#{define} #{element.type} #{get}(#{type}* self, #{element.type} element) {
|
318
|
+
#{element.type} result;
|
319
|
+
#{assert}(self);
|
320
|
+
#{assert}(#{contains}(self, element));
|
321
|
+
result = #{@list.find}(&self->buckets[#{element.identify("element")} % self->bucket_count], element);
|
322
|
+
return result;
|
323
|
+
}
|
324
|
+
#{define} size_t #{size}(#{type}* self) {
|
325
|
+
#{assert}(self);
|
326
|
+
return self->size;
|
327
|
+
}
|
328
|
+
#{define} int #{put}(#{type}* self, #{element.type} element) {
|
329
|
+
#{@list.type}* bucket;
|
330
|
+
#{assert}(self);
|
331
|
+
bucket = &self->buckets[#{element.identify("element")} % self->bucket_count];
|
332
|
+
if(!#{@list.contains}(bucket, element)) {
|
333
|
+
#{@list.push}(bucket, element);
|
334
|
+
++self->size;
|
335
|
+
#{rehash}(self);
|
336
|
+
return 1;
|
337
|
+
}
|
338
|
+
return 0;
|
339
|
+
}
|
340
|
+
#{define} int #{replace}(#{type}* self, #{element.type} element) {
|
341
|
+
#{@list.type}* bucket;
|
342
|
+
#{assert}(self);
|
343
|
+
bucket = &self->buckets[#{element.identify("element")} % self->bucket_count];
|
344
|
+
return #{@list.replace}(bucket, element);
|
345
|
+
}
|
346
|
+
#{define} int #{remove}(#{type}* self, #{element.type} element) {
|
347
|
+
#{@list.type}* bucket;
|
348
|
+
#{assert}(self);
|
349
|
+
bucket = &self->buckets[#{element.identify("element")} % self->bucket_count];
|
350
|
+
if(#{@list.remove}(bucket, element)) {
|
351
|
+
--self->size;
|
352
|
+
#{rehash}(self);
|
353
|
+
return 1;
|
354
|
+
}
|
355
|
+
return 0;
|
356
|
+
}
|
357
|
+
#{define} void #{exclude}(#{type}* self, #{type}* other) {
|
358
|
+
#{it} it;
|
359
|
+
#{assert}(self);
|
360
|
+
#{assert}(other);
|
361
|
+
#{itCtor}(&it, other);
|
362
|
+
while(#{itMove}(&it)) #{remove}(self, *#{itGetRef}(&it));
|
363
|
+
}
|
364
|
+
#{define} void #{include}(#{type}* self, #{type}* other) {
|
365
|
+
#{it} it;
|
366
|
+
#{assert}(self);
|
367
|
+
#{assert}(other);
|
368
|
+
#{itCtor}(&it, other);
|
369
|
+
while(#{itMove}(&it)) #{put}(self, *#{itGetRef}(&it));
|
370
|
+
}
|
371
|
+
#{define} void #{retain}(#{type}* self, #{type}* other) {
|
372
|
+
#{it} it;
|
373
|
+
#{type} set;
|
374
|
+
#{assert}(self);
|
375
|
+
#{assert}(other);
|
376
|
+
#{ctor}(&set);
|
377
|
+
#{itCtor}(&it, self);
|
378
|
+
while(#{itMove}(&it)) {
|
379
|
+
#{element.type}* e = #{itGetRef}(&it);
|
380
|
+
if(#{contains}(other, *e)) #{put}(&set, *e);
|
381
|
+
}
|
382
|
+
#{dtor}(self);
|
383
|
+
*self = set;
|
384
|
+
}
|
385
|
+
#{define} void #{invert}(#{type}* self, #{type}* other) {
|
386
|
+
#{it} it;
|
387
|
+
#{type} set;
|
388
|
+
#{assert}(self);
|
389
|
+
#{assert}(other);
|
390
|
+
#{ctor}(&set);
|
391
|
+
#{itCtor}(&it, self);
|
392
|
+
while(#{itMove}(&it)) {
|
393
|
+
#{element.type}* e = #{itGetRef}(&it);
|
394
|
+
if(!#{contains}(other, *e)) #{put}(&set, *e);
|
395
|
+
}
|
396
|
+
#{itCtor}(&it, other);
|
397
|
+
while(#{itMove}(&it)) {
|
398
|
+
#{element.type}* e = #{itGetRef}(&it);
|
399
|
+
if(!#{contains}(self, *e)) #{put}(&set, *e);
|
400
|
+
}
|
401
|
+
#{dtor}(self);
|
402
|
+
*self = set;
|
403
|
+
}
|
404
|
+
#{define} void #{itCtor}(#{it}* self, #{type}* set) {
|
405
|
+
#{assert}(self);
|
406
|
+
self->set = set;
|
407
|
+
self->bucket_index = -1;
|
408
|
+
}
|
409
|
+
#{define} int #{itMove}(#{it}* self) {
|
410
|
+
#{assert}(self);
|
411
|
+
if(self->bucket_index < 0) #{@list.itCtor}(&self->it, &self->set->buckets[self->bucket_index = 0]);
|
412
|
+
if(#{@list.itMove}(&self->it)) return 1;
|
413
|
+
while(++self->bucket_index < self->set->bucket_count) {
|
414
|
+
#{@list.itCtor}(&self->it, &self->set->buckets[self->bucket_index]);
|
415
|
+
if(#{@list.itMove}(&self->it)) return 1;
|
416
|
+
}
|
417
|
+
return 0;
|
418
|
+
}
|
419
|
+
#{define} #{element.type} #{itGet}(#{it}* self) {
|
420
|
+
#{assert}(self);
|
421
|
+
return #{@list.itGet}(&self->it);
|
422
|
+
}
|
423
|
+
#{define} #{element.type}* #{itGetRef}(#{it}* self) {
|
424
|
+
#{assert}(self);
|
425
|
+
return #{@list.itGetRef}(&self->it);
|
426
|
+
}
|
427
|
+
$
|
428
|
+
end
|
429
|
+
|
430
|
+
end # HashSet
|
431
|
+
|
432
|
+
|
433
|
+
end # AutoC
|
@@ -0,0 +1,410 @@
|
|
1
|
+
require "autoc/collection"
|
2
|
+
|
3
|
+
|
4
|
+
module AutoC
|
5
|
+
|
6
|
+
|
7
|
+
=begin
|
8
|
+
|
9
|
+
List is an ordered unidirectional sequence container.
|
10
|
+
List supports submission/polling operations at one end hence it can be used as a LIFO container.
|
11
|
+
|
12
|
+
The collection's C++ counterpart is +std::forward_list<>+ template class.
|
13
|
+
|
14
|
+
== Generated C interface
|
15
|
+
|
16
|
+
=== Collection management
|
17
|
+
|
18
|
+
[cols=2*]
|
19
|
+
|===
|
20
|
+
|*_void_* ~type~Copy(*_Type_* * +dst+, *_Type_* * +src+)
|
21
|
+
|
|
22
|
+
Create a new list +dst+ filled with the contents of +src+.
|
23
|
+
A copy operation is performed on every element in +src+.
|
24
|
+
|
25
|
+
NOTE: Previous contents of +dst+ is overwritten.
|
26
|
+
|
27
|
+
|*_void_* ~type~Ctor(*_Type_* * +self+)
|
28
|
+
|
|
29
|
+
Create a new empty list +self+.
|
30
|
+
|
31
|
+
NOTE: Previous contents of +self+ is overwritten.
|
32
|
+
|
33
|
+
|*_void_* ~type~Dtor(*_Type_* * +self+)
|
34
|
+
|
|
35
|
+
Destroy list +self+.
|
36
|
+
Stored elements are destroyed as well by calling the respective destructors.
|
37
|
+
|
38
|
+
|*_int_* ~type~Equal(*_Type_* * +lt+, *_Type_* * +rt+)
|
39
|
+
|
|
40
|
+
Return non-zero value if lists +lt+ and +rt+ are considered equal by contents and zero value otherwise.
|
41
|
+
|
42
|
+
|*_size_t_* ~type~Identify(*_Type_* * +self+)
|
43
|
+
|
|
44
|
+
Return hash code for list +self+.
|
45
|
+
|===
|
46
|
+
|
47
|
+
=== Basic operations
|
48
|
+
|
49
|
+
[cols=2*]
|
50
|
+
|===
|
51
|
+
|*_int_* ~type~Contains(*_Type_* * +self+, *_E_* +what+)
|
52
|
+
|
|
53
|
+
Return non-zero value if list +self+ contains (at least) one element considered equal to +what+ and zero value otherwise.
|
54
|
+
|
55
|
+
|*_int_* ~type~Empty(*_Type_* * +self+)
|
56
|
+
|
|
57
|
+
Return non-zero value if list +self+ contains no elements and zero value otherwise.
|
58
|
+
|
59
|
+
|*_E_* ~type~Find(*_Type_* * +self+, *_E_* +what+)
|
60
|
+
|
|
61
|
+
Return the _first_ element of stored in +self+ which is considered equal to +what+.
|
62
|
+
|
63
|
+
WARNING: +self+ *must* contain such element otherwise the behavior is undefined. See ~type~Contains().
|
64
|
+
|
65
|
+
|*_E_* ~type~Peek(*_Type_* * +self+)
|
66
|
+
|
|
67
|
+
Return a _copy_ of the head element of +self+.
|
68
|
+
|
69
|
+
WARNING: +self+ *must not* be empty otherwise the behavior is undefined. See ~type~Empty().
|
70
|
+
|
71
|
+
|*_E_* ~type~Pop(*_Type_* * +self+)
|
72
|
+
|
|
73
|
+
Remove head element of +self+ *and* return it.
|
74
|
+
|
75
|
+
NOTE: The function returns the element itself, *not* a copy.
|
76
|
+
|
77
|
+
WARNING: +self+ *must not* be empty otherwise the behavior is undefined. See ~type~Empty().
|
78
|
+
|
79
|
+
|*_void_* ~type~Purge(*_Type_* * +self+)
|
80
|
+
|
|
81
|
+
Remove and destroy all elements stored in +self+.
|
82
|
+
|
83
|
+
|*_void_* ~type~Push(*_Type_* * +self+, *_E_* +what+)
|
84
|
+
|
|
85
|
+
Place a _copy_ of the element +what+ to the head of +self+.
|
86
|
+
|
87
|
+
|*_int_* ~type~Replace(*_Type_* * +self+, *_E_* +with+)
|
88
|
+
|
|
89
|
+
Find the _first_ occurrence of +with+ in +self+ and replace it with a _copy_ of the element +with+.
|
90
|
+
Replaced element is destroyed.
|
91
|
+
|
92
|
+
Return non-zero value on successful replacement and zero value if no suitable element was found.
|
93
|
+
|
94
|
+
|*_int_* ~type~ReplaceAll(*_Type_* * +self+, *_E_* +with+)
|
95
|
+
|
|
96
|
+
Find _all_ occurrences of +with+ in +self+ and replace them with _copies_ of the element +with+.
|
97
|
+
All replaced elements are destroyed.
|
98
|
+
|
99
|
+
Return number of successful replacements.
|
100
|
+
|
101
|
+
|*_int_* ~type~ReplaceEx(*_Type_* * +self+, *_E_* +with+, *_int_* count)
|
102
|
+
|
|
103
|
+
Find at most +count+ occurrences of +with+ in +self+ and replace them with _copies_ of the element +with+.
|
104
|
+
If +count+ is negative, _all_ occurrences are replaced instead.
|
105
|
+
All replaced elements are destroyed.
|
106
|
+
|
107
|
+
Return number of successful replacements.
|
108
|
+
|
109
|
+
|*_int_* ~type~Remove(*_Type_* * +self+, *_E_* +what+)
|
110
|
+
|
|
111
|
+
Remove and destroy the _first_ occurrence of the element +what+ in +self+.
|
112
|
+
|
113
|
+
Return non-zero value if element was removed and zero value otherwise.
|
114
|
+
|
115
|
+
|*_int_* ~type~RemoveAll(*_Type_* * +self+, *_E_* +what+)
|
116
|
+
|
|
117
|
+
Remove and destroy _all_ occurrences of the element +what+ in +self+.
|
118
|
+
|
119
|
+
Return number of elements actually removed.
|
120
|
+
|
121
|
+
|*_int_* ~type~RemoveEx(*_Type_* * +self+, *_E_* +what+, *_int_* count)
|
122
|
+
|
|
123
|
+
Remove and destroy at most +count+ occurrences of the element +what+ in +self+.
|
124
|
+
If +count+ is negative, _all_ occurrences are removed instead.
|
125
|
+
|
126
|
+
Return number of elements actually removed.
|
127
|
+
|
128
|
+
|*_size_t_* ~type~Size(*_Type_* * +self+)
|
129
|
+
|
|
130
|
+
Return number of elements stored in +self+.
|
131
|
+
|===
|
132
|
+
|
133
|
+
=== Iteration
|
134
|
+
|
135
|
+
[cols=2*]
|
136
|
+
|===
|
137
|
+
|*_void_* ~it~Ctor(*_IteratorType_* * +it+, *_Type_* * +self+)
|
138
|
+
|
|
139
|
+
Create a new iterator +it+ on list +self+.
|
140
|
+
|
141
|
+
NOTE: Previous contents of +it+ is overwritten.
|
142
|
+
|
143
|
+
|*_int_* ~it~Move(*_IteratorType_* * +it+)
|
144
|
+
|
|
145
|
+
Advance iterator position of +it+ *and* return non-zero value if new position is valid and zero value otherwise.
|
146
|
+
|
147
|
+
|*_E_* ~it~Get(*_IteratorType_* * +it+)
|
148
|
+
|
|
149
|
+
Return a _copy_ of current element pointed to by the iterator +it+.
|
150
|
+
|
151
|
+
WARNING: current position *must* be valid otherwise the behavior is undefined. See ~it~Move().
|
152
|
+
|===
|
153
|
+
|
154
|
+
=end
|
155
|
+
class List < Collection
|
156
|
+
|
157
|
+
def write_exported_types(stream)
|
158
|
+
stream << %$
|
159
|
+
/***
|
160
|
+
**** #{type}<#{element.type}> (#{self.class})
|
161
|
+
***/
|
162
|
+
$ if public?
|
163
|
+
stream << %$
|
164
|
+
typedef struct #{node} #{node};
|
165
|
+
typedef struct #{type} #{type};
|
166
|
+
typedef struct #{it} #{it};
|
167
|
+
struct #{type} {
|
168
|
+
#{node}* head_node;
|
169
|
+
size_t node_count;
|
170
|
+
};
|
171
|
+
struct #{it} {
|
172
|
+
int start;
|
173
|
+
#{type}* list;
|
174
|
+
#{node}* this_node;
|
175
|
+
};
|
176
|
+
struct #{node} {
|
177
|
+
#{element.type} element;
|
178
|
+
#{node}* next_node;
|
179
|
+
};
|
180
|
+
$
|
181
|
+
end
|
182
|
+
|
183
|
+
def write_exported_declarations(stream, declare, define)
|
184
|
+
stream << %$
|
185
|
+
#{declare} void #{ctor}(#{type}*);
|
186
|
+
#{declare} void #{dtor}(#{type}*);
|
187
|
+
#{declare} void #{copy}(#{type}*, #{type}*);
|
188
|
+
#{declare} int #{equal}(#{type}*, #{type}*);
|
189
|
+
#{declare} size_t #{identify}(#{type}*);
|
190
|
+
#{declare} void #{purge}(#{type}*);
|
191
|
+
#{declare} #{element.type} #{peek}(#{type}*);
|
192
|
+
#{declare} #{element.type} #{pop}(#{type}*);
|
193
|
+
#{declare} void #{push}(#{type}*, #{element.type});
|
194
|
+
#{declare} int #{contains}(#{type}*, #{element.type});
|
195
|
+
#{declare} #{element.type} #{find}(#{type}*, #{element.type});
|
196
|
+
#define #{replace}(self, with) #{replaceEx}(self, with, 1)
|
197
|
+
#define #{replaceAll}(self, with) #{replaceEx}(self, with, -1)
|
198
|
+
#{declare} int #{replaceEx}(#{type}*, #{element.type}, int);
|
199
|
+
#define #{remove}(self, what) #{removeEx}(self, what, 1)
|
200
|
+
#define #{removeAll}(self, what) #{removeEx}(self, what, -1)
|
201
|
+
#{declare} int #{removeEx}(#{type}*, #{element.type}, int);
|
202
|
+
#{declare} size_t #{size}(#{type}*);
|
203
|
+
#define #{empty}(self) (#{size}(self) == 0)
|
204
|
+
#{declare} void #{itCtor}(#{it}*, #{type}*);
|
205
|
+
#{declare} int #{itMove}(#{it}*);
|
206
|
+
#{declare} #{element.type} #{itGet}(#{it}*);
|
207
|
+
$
|
208
|
+
end
|
209
|
+
|
210
|
+
def write_implementations(stream, define)
|
211
|
+
stream << %$
|
212
|
+
#{define} #{element.type}* #{itGetRef}(#{it}*);
|
213
|
+
#{define} void #{ctor}(#{type}* self) {
|
214
|
+
#{assert}(self);
|
215
|
+
self->head_node = NULL;
|
216
|
+
self->node_count = 0;
|
217
|
+
}
|
218
|
+
#{define} void #{dtor}(#{type}* self) {
|
219
|
+
#{node}* node;
|
220
|
+
#{assert}(self);
|
221
|
+
node = self->head_node;
|
222
|
+
while(node) {
|
223
|
+
#{node}* this_node = node;
|
224
|
+
node = node->next_node;
|
225
|
+
#{element.dtor("this_node->element")};
|
226
|
+
#{free}(this_node);
|
227
|
+
}
|
228
|
+
}
|
229
|
+
#{define} void #{copy}(#{type}* dst, #{type}* src) {
|
230
|
+
#{it} it;
|
231
|
+
#{assert}(src);
|
232
|
+
#{assert}(dst);
|
233
|
+
#{ctor}(dst);
|
234
|
+
#{itCtor}(&it, src);
|
235
|
+
while(#{itMove}(&it)) {
|
236
|
+
#{push}(dst, *#{itGetRef}(&it));
|
237
|
+
}
|
238
|
+
}
|
239
|
+
#{define} int #{equal}(#{type}* lt, #{type}* rt) {
|
240
|
+
if(#{size}(lt) == #{size}(rt)) {
|
241
|
+
#{it} lit, rit;
|
242
|
+
#{itCtor}(&lit, lt);
|
243
|
+
#{itCtor}(&rit, rt);
|
244
|
+
while(#{itMove}(&lit) && #{itMove}(&rit)) {
|
245
|
+
int equal;
|
246
|
+
#{element.type} *le, *re;
|
247
|
+
le = #{itGetRef}(&lit);
|
248
|
+
re = #{itGetRef}(&rit);
|
249
|
+
equal = #{element.equal("*le", "*re")};
|
250
|
+
if(!equal) return 0;
|
251
|
+
}
|
252
|
+
return 1;
|
253
|
+
} else
|
254
|
+
return 0;
|
255
|
+
}
|
256
|
+
#{define} size_t #{identify}(#{type}* self) {
|
257
|
+
#{node}* node;
|
258
|
+
size_t result = 0;
|
259
|
+
#{assert}(self);
|
260
|
+
for(node = self->head_node; node != NULL; node = node->next_node) {
|
261
|
+
result ^= #{element.identify("node->element")};
|
262
|
+
result = AUTOC_RCYCLE(result);
|
263
|
+
}
|
264
|
+
return result;
|
265
|
+
}
|
266
|
+
#{define} void #{purge}(#{type}* self) {
|
267
|
+
#{dtor}(self);
|
268
|
+
#{ctor}(self);
|
269
|
+
}
|
270
|
+
#{define} #{element.type} #{peek}(#{type}* self) {
|
271
|
+
#{element.type} result;
|
272
|
+
#{assert}(self);
|
273
|
+
#{assert}(!#{empty}(self));
|
274
|
+
#{element.copy("result", "self->head_node->element")};
|
275
|
+
return result;
|
276
|
+
}
|
277
|
+
#{define} #{element.type} #{pop}(#{type}* self) {
|
278
|
+
#{node}* node;
|
279
|
+
#{element.type} result;
|
280
|
+
#{assert}(self);
|
281
|
+
#{assert}(!#{empty}(self));
|
282
|
+
node = self->head_node;
|
283
|
+
result = node->element;
|
284
|
+
self->head_node = self->head_node->next_node;
|
285
|
+
--self->node_count;
|
286
|
+
#{free}(node);
|
287
|
+
return result;
|
288
|
+
}
|
289
|
+
#{define} void #{push}(#{type}* self, #{element.type} element) {
|
290
|
+
#{node}* node;
|
291
|
+
#{assert}(self);
|
292
|
+
node = (#{node}*)#{malloc}(sizeof(#{node})); #{assert}(node);
|
293
|
+
#{element.copy("node->element", "element")};
|
294
|
+
node->next_node = self->head_node;
|
295
|
+
self->head_node = node;
|
296
|
+
++self->node_count;
|
297
|
+
}
|
298
|
+
#{define} int #{contains}(#{type}* self, #{element.type} what) {
|
299
|
+
#{node}* node;
|
300
|
+
int found = 0;
|
301
|
+
#{assert}(self);
|
302
|
+
node = self->head_node;
|
303
|
+
while(node) {
|
304
|
+
if(#{element.equal("node->element", "what")}) {
|
305
|
+
found = 1;
|
306
|
+
break;
|
307
|
+
}
|
308
|
+
node = node->next_node;
|
309
|
+
}
|
310
|
+
return found;
|
311
|
+
}
|
312
|
+
#{define} #{element.type} #{find}(#{type}* self, #{element.type} what) {
|
313
|
+
#{node}* node;
|
314
|
+
#{assert}(self);
|
315
|
+
#{assert}(#{contains}(self, what));
|
316
|
+
node = self->head_node;
|
317
|
+
while(node) {
|
318
|
+
if(#{element.equal("node->element", "what")}) {
|
319
|
+
#{element.type} result;
|
320
|
+
#{element.copy("result", "node->element")};
|
321
|
+
return result;
|
322
|
+
}
|
323
|
+
node = node->next_node;
|
324
|
+
}
|
325
|
+
#{abort}();
|
326
|
+
}
|
327
|
+
#{define} int #{replaceEx}(#{type}* self, #{element.type} with, int count) {
|
328
|
+
#{node}* node;
|
329
|
+
int replaced = 0;
|
330
|
+
#{assert}(self);
|
331
|
+
if(count == 0) return 0;
|
332
|
+
node = self->head_node;
|
333
|
+
while(node) {
|
334
|
+
if(#{element.equal("node->element", "with")}) {
|
335
|
+
#{element.dtor("node->element")};
|
336
|
+
#{element.copy("node->element", "with")};
|
337
|
+
++replaced;
|
338
|
+
if(count > 0 && replaced >= count) break;
|
339
|
+
}
|
340
|
+
node = node->next_node;
|
341
|
+
}
|
342
|
+
return replaced;
|
343
|
+
}
|
344
|
+
#{define} int #{removeEx}(#{type}* self, #{element.type} what, int count) {
|
345
|
+
#{node} *node, *prev_node;
|
346
|
+
int removed = 0;
|
347
|
+
#{assert}(self);
|
348
|
+
if(count == 0) return 0;
|
349
|
+
node = self->head_node;
|
350
|
+
prev_node = NULL;
|
351
|
+
while(node) {
|
352
|
+
if(#{element.equal("node->element", "what")}) {
|
353
|
+
#{node}* this_node;
|
354
|
+
if(prev_node) {
|
355
|
+
this_node = prev_node->next_node = node->next_node;
|
356
|
+
} else {
|
357
|
+
this_node = self->head_node = node->next_node;
|
358
|
+
}
|
359
|
+
++removed;
|
360
|
+
--self->node_count;
|
361
|
+
#{element.dtor("node->element")};
|
362
|
+
#{free}(node);
|
363
|
+
node = this_node;
|
364
|
+
if(count > 0 && removed >= count) break;
|
365
|
+
} else {
|
366
|
+
prev_node = node;
|
367
|
+
node = node->next_node;
|
368
|
+
}
|
369
|
+
}
|
370
|
+
return removed;
|
371
|
+
}
|
372
|
+
#{define} size_t #{size}(#{type}* self) {
|
373
|
+
#{assert}(self);
|
374
|
+
return self->node_count;
|
375
|
+
}
|
376
|
+
#{define} void #{itCtor}(#{it}* self, #{type}* list) {
|
377
|
+
#{assert}(self);
|
378
|
+
#{assert}(list);
|
379
|
+
self->start = 1;
|
380
|
+
self->list = list;
|
381
|
+
}
|
382
|
+
#{define} int #{itMove}(#{it}* self) {
|
383
|
+
#{assert}(self);
|
384
|
+
if(self->start) {
|
385
|
+
self->this_node = self->list->head_node;
|
386
|
+
self->start = 0;
|
387
|
+
} else {
|
388
|
+
self->this_node = self->this_node ? self->this_node->next_node : NULL;
|
389
|
+
}
|
390
|
+
return self->this_node != NULL;
|
391
|
+
}
|
392
|
+
#{define} #{element.type} #{itGet}(#{it}* self) {
|
393
|
+
#{element.type} result;
|
394
|
+
#{assert}(self);
|
395
|
+
#{assert}(self->this_node);
|
396
|
+
#{element.copy("result", "self->this_node->element")};
|
397
|
+
return result;
|
398
|
+
}
|
399
|
+
#{define} #{element.type}* #{itGetRef}(#{it}* self) {
|
400
|
+
#{assert}(self);
|
401
|
+
#{assert}(self->this_node);
|
402
|
+
return &self->this_node->element;
|
403
|
+
}
|
404
|
+
$
|
405
|
+
end
|
406
|
+
|
407
|
+
end # List
|
408
|
+
|
409
|
+
|
410
|
+
end # AutoC
|