autoc 0.8 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
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