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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/README +15 -4
  3. data/doc/AutoC.html +245 -0
  4. data/doc/AutoC/Code.html +520 -0
  5. data/doc/AutoC/Collection.html +923 -0
  6. data/doc/AutoC/HashMap.html +1161 -0
  7. data/doc/AutoC/HashSet.html +1122 -0
  8. data/doc/AutoC/List.html +1002 -0
  9. data/doc/AutoC/Module.html +951 -0
  10. data/doc/AutoC/Module/File.html +412 -0
  11. data/doc/AutoC/Module/Header.html +432 -0
  12. data/doc/AutoC/Module/Source.html +704 -0
  13. data/doc/AutoC/Priority.html +138 -0
  14. data/doc/AutoC/Queue.html +1167 -0
  15. data/doc/AutoC/Type.html +1152 -0
  16. data/doc/AutoC/UserDefinedType.html +655 -0
  17. data/doc/AutoC/Vector.html +856 -0
  18. data/doc/_index.html +299 -0
  19. data/doc/class_list.html +54 -0
  20. data/doc/css/common.css +1 -0
  21. data/doc/css/full_list.css +57 -0
  22. data/doc/css/style.css +339 -0
  23. data/doc/file.README.html +112 -0
  24. data/doc/file_list.html +56 -0
  25. data/doc/frames.html +26 -0
  26. data/doc/index.html +112 -0
  27. data/doc/js/app.js +219 -0
  28. data/doc/js/full_list.js +178 -0
  29. data/doc/js/jquery.js +4 -0
  30. data/doc/method_list.html +605 -0
  31. data/doc/top-level-namespace.html +112 -0
  32. data/lib/autoc.rb +35 -12
  33. data/lib/autoc/{code_builder.rb → code.rb} +230 -247
  34. data/lib/autoc/collection.rb +137 -0
  35. data/lib/autoc/collection/hash_map.rb +388 -0
  36. data/lib/autoc/collection/hash_set.rb +433 -0
  37. data/lib/autoc/collection/list.rb +410 -0
  38. data/lib/autoc/collection/queue.rb +514 -0
  39. data/lib/autoc/collection/vector.rb +295 -0
  40. data/lib/autoc/type.rb +198 -0
  41. data/test/test.c +921 -396
  42. data/test/test.h +41 -0
  43. data/test/test.rb +21 -26
  44. data/test/test_auto.c +2630 -3961
  45. data/test/test_auto.h +449 -560
  46. metadata +50 -17
  47. data/lib/autoc/data_struct_builder.rb +0 -1794
  48. data/lib/autoc/type_builder.rb +0 -24
  49. 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