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,137 @@
1
+ require "autoc/code"
2
+ require "autoc/type"
3
+
4
+
5
+ module AutoC
6
+
7
+
8
+ =begin
9
+
10
+ == Implemented collections
11
+
12
+ - {AutoC::Vector} a fixed-sized array
13
+
14
+ - {AutoC::List} a single linked list
15
+
16
+ - {AutoC::Queue} a double linked list
17
+
18
+ - {AutoC::HashSet} a hash-based set
19
+
20
+ - {AutoC::HashMap} a hash-based map
21
+
22
+ == Ruby side operation
23
+
24
+ .Complete example for generation of a list of integers collection:
25
+ [source,ruby]
26
+ ----
27
+ require "autoc"
28
+ AutoC::Module.generate!(:Test) do |c|
29
+ c << AutoC::List.new(:IntList, :int)
30
+ end
31
+ ----
32
+ In the above example a C module Test represented by the C header +test_auto.h+ and the C source +test_auto.c+ are generated.
33
+ The C++ counterpart of the generated collection is +std::forward_list<int>+.
34
+
35
+ == C interface
36
+
37
+ === Element types: values, references
38
+
39
+ === Thread safety
40
+
41
+ WARNING: In its current state the implemented collections are *not* thread-safe.
42
+
43
+ === Iteration
44
+
45
+ At the moment a fairly simple iteration functionality is implemented.
46
+ The iterators are modeled after the C# language.
47
+ All implemented iterators do not require destruction after use.
48
+
49
+ .Basic iterator usage example:
50
+ [source,c]
51
+ ----
52
+ MyVector c;
53
+ MyVectorIt it;
54
+ ...
55
+ MyVectorItCtor(&it, &c);
56
+ while(MyVectorItMove(&it)) {
57
+ Element e = MyVectorItGet(&it);
58
+ ...
59
+ ElementDtor(e);
60
+ }
61
+ ----
62
+
63
+ WARNING: the collection being iterated *must not* be modified in any way otherwise the iterator behavior is undefined.
64
+ =end
65
+ class Collection < Type
66
+
67
+ def self.coerce(type)
68
+ type.is_a?(Type) ? type : UserDefinedType.new(type)
69
+ end
70
+
71
+ attr_reader :element
72
+
73
+ def entities; super + [element] end
74
+
75
+ def initialize(type_name, element_type, visibility = :public)
76
+ super(type_name, visibility)
77
+ @element = Collection.coerce(element_type)
78
+ end
79
+
80
+ def ctor(*args)
81
+ if args.empty?
82
+ super()
83
+ else
84
+ check_args(args, 1)
85
+ obj = args.first
86
+ super() + "(&#{obj})"
87
+ end
88
+ end
89
+
90
+ def dtor(*args)
91
+ if args.empty?
92
+ super()
93
+ else
94
+ check_args(args, 1)
95
+ obj = args.first
96
+ super() + "(&#{obj})"
97
+ end
98
+ end
99
+
100
+ def copy(*args)
101
+ if args.empty?
102
+ super()
103
+ else
104
+ check_args(args, 2)
105
+ dst, src = args
106
+ super() + "(&#{dst}, &#{src})"
107
+ end
108
+ end
109
+
110
+ def equal(*args)
111
+ if args.empty?
112
+ super()
113
+ else
114
+ check_args(args, 2)
115
+ lt, rt = args
116
+ super() + "(&#{lt}, &#{rt})"
117
+ end
118
+ end
119
+
120
+ def less(*args)
121
+ args.empty? ? super() : raise("#{self.class} provides no ordering functionality")
122
+ end
123
+
124
+ def identify(*args)
125
+ args.empty? ? super() : raise("#{self.class} provides no hashing functionality")
126
+ end
127
+
128
+ private
129
+
130
+ def check_args(args, nargs)
131
+ raise "expected exactly #{nargs} argument(s)" unless args.size == nargs
132
+ end
133
+
134
+ end # Collection
135
+
136
+
137
+ end # AutoC
@@ -0,0 +1,388 @@
1
+ require "autoc/collection"
2
+ require "autoc/collection/hash_set"
3
+
4
+
5
+ module AutoC
6
+
7
+
8
+ =begin
9
+
10
+ HashSet is a hash-based unordered random access container holding unique keys with each key having an element bound to it.
11
+
12
+ The collection's C++ counterpart is +std::unordered_map<>+ 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 map +dst+ filled with the contents of +src+.
23
+ A copy operation is performed on all keys and values in +src+.
24
+
25
+ NOTE: Previous contents of +dst+ is overwritten.
26
+
27
+ |*_void_* ~type~Ctor(*_Type_* * +self+)
28
+ |
29
+ Create a new empty map +self+.
30
+
31
+ NOTE: Previous contents of +self+ is overwritten.
32
+
33
+ |*_void_* ~type~Dtor(*_Type_* * +self+)
34
+ |
35
+ Destroy map +self+.
36
+ Stored keys and values 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 maps +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 map +self+.
45
+ |===
46
+
47
+ === Basic operations
48
+
49
+ [cols=2*]
50
+ |===
51
+ |*_int_* ~type~ContainsKey(*_Type_* * +self+, *_K_* +key+)
52
+ |
53
+ Return non-zero value if map +self+ contains an entry with a key considered equal to the key +key+ and zero value otherwise.
54
+
55
+ |*_int_* ~type~Empty(*_Type_* * +self+)
56
+ |
57
+ Return non-zero value if map +self+ contains no entries and zero value otherwise.
58
+
59
+ |*_E_* ~type~Get(*_Type_* * +self+, *_K_* +key+)
60
+ |
61
+ Return a _copy_ of the element in +self+ bound to a key which is considered equal to the key +key+.
62
+
63
+ WARNING: +self+ *must* contain such key otherwise the behavior is undefined. See ~type~Contains().
64
+
65
+ |*_void_* ~type~Purge(*_Type_* * +self+)
66
+ |
67
+ Remove and destroy all keys and elements stored in +self+.
68
+
69
+ |*_int_* ~type~Put(*_Type_* * +self+, *_K_* +key+, *_E_* +value+)
70
+ |
71
+ Put a _copy_ of the element +value+ bound to a _copy_ of the key +key+ into +self+ *only if* there is no such key in +self+ which is considered equal to +key+.
72
+
73
+ Return non-zero value on successful put and zero value otherwise.
74
+
75
+ |*_int_* ~type~Replace(*_Type_* * +self+, *_K_* +key+, *_E_* +value+)
76
+ |
77
+ If +self+ contains a key which is considered equal to the key +key+,
78
+ remove and destroy that key along with an element bound to it
79
+ and put a new pair built of the _copies_ of +key+ and +value+,
80
+ otherwise simply put a new key/element pair into +self+ in the way of ~type~Put().
81
+
82
+ Return non-zero value if the replacement was actually performed and zero value otherwise.
83
+
84
+ |*_int_* ~type~Remove(*_Type_* * +self+, *_K_* +key+)
85
+ |
86
+ Remove and destroy a key which is considered equal to the key +key+.
87
+ Destroy an element bound to that key.
88
+
89
+ Return non-zero value on successful key/element pair removal and zero value otherwise.
90
+
91
+ |*_size_t_* ~type~Size(*_Type_* * +self+)
92
+ |
93
+ Return number of key/element pairs stored in +self+.
94
+ |===
95
+
96
+ === Iteration
97
+
98
+ [cols=2*]
99
+ |===
100
+ |*_void_* ~it~Ctor(*_IteratorType_* * +it+, *_Type_* * +self+)
101
+ |
102
+ Create a new iterator +it+ on map +self+.
103
+
104
+ NOTE: As the map is an unordered sequence, the traversal order is unspecified.
105
+
106
+ NOTE: Previous contents of +it+ is overwritten.
107
+
108
+ |*_int_* ~it~Move(*_IteratorType_* * +it+)
109
+ |
110
+ Advance iterator position of +it+ *and* return non-zero value if new position is valid and zero value otherwise.
111
+
112
+ |*_K_* ~it~GetKey(*_IteratorType_* * +it+)
113
+ |
114
+ Return a _copy_ of the key from a key/value pair pointed to by the iterator +it+.
115
+
116
+ WARNING: current position *must* be valid otherwise the behavior is undefined. See ~it~Move().
117
+
118
+ |*_E_* ~it~GetElement(*_IteratorType_* * +it+)
119
+ |
120
+ Return a _copy_ of the element from a key/element pair pointed to by the iterator +it+.
121
+
122
+ WARNING: current position *must* be valid otherwise the behavior is undefined. See ~it~Move().
123
+
124
+ |*_E_* ~it~Get(*_IteratorType_* * +it+)
125
+ |
126
+ Alias for ~it~GetElement().
127
+ |===
128
+
129
+ =end
130
+ class HashMap < Collection
131
+
132
+ attr_reader :key
133
+
134
+ alias :value :element
135
+
136
+ def entities; super + [key] end
137
+
138
+ def initialize(type, key_type, value_type, visibility = :public)
139
+ super(type, value_type, visibility)
140
+ @key = Collection.coerce(key_type)
141
+ @entry = UserDefinedType.new(:type => entry, :identify => entryIdentify, :equal => entryEqual, :copy => entryCopy, :dtor => entryDtor)
142
+ @set = HashSet.new(set, @entry, :static)
143
+ end
144
+
145
+ def write_exported_types(stream)
146
+ stream << %$
147
+ /***
148
+ **** #{type}<#{key.type},#{value.type}> (#{self.class})
149
+ ***/
150
+ $ if public?
151
+ stream << %$
152
+ typedef struct #{@entry.type} #{@entry.type};
153
+ struct #{@entry.type} {
154
+ #{key.type} key;
155
+ #{value.type} value;
156
+ unsigned flags;
157
+ };
158
+ $
159
+ @set.write_exported_types(stream)
160
+ stream << %$
161
+ typedef struct #{type} #{type};
162
+ typedef struct #{it} #{it};
163
+ struct #{type} {
164
+ #{@set.type} entries;
165
+ };
166
+ struct #{it} {
167
+ #{@set.it} it;
168
+ };
169
+ $
170
+ end
171
+
172
+ def write_exported_declarations(stream, declare, define)
173
+ stream << %$
174
+ #{declare} void #{ctor}(#{type}*);
175
+ #{declare} void #{dtor}(#{type}*);
176
+ #{declare} void #{copy}(#{type}*, #{type}*);
177
+ #{declare} int #{equal}(#{type}*, #{type}*);
178
+ #{declare} size_t #{identify}(#{type}*);
179
+ #{declare} void #{purge}(#{type}*);
180
+ #{declare} size_t #{size}(#{type}*);
181
+ #define #{empty}(self) (#{size}(self) == 0)
182
+ #{declare} int #{containsKey}(#{type}*, #{key.type});
183
+ #{declare} #{value.type} #{get}(#{type}*, #{key.type});
184
+ #{declare} int #{put}(#{type}*, #{key.type}, #{value.type});
185
+ #{declare} int #{replace}(#{type}*, #{key.type}, #{value.type});
186
+ #{declare} int #{remove}(#{type}*, #{key.type});
187
+ #{declare} void #{itCtor}(#{it}*, #{type}*);
188
+ #{declare} int #{itMove}(#{it}*);
189
+ #{declare} #{key.type} #{itGetKey}(#{it}*);
190
+ #{declare} #{value.type} #{itGetElement}(#{it}*);
191
+ #define #{itGet}(it) #{itGetElement}(it)
192
+ $
193
+ end
194
+
195
+ def write_implementations(stream, define)
196
+ stream << %$
197
+ #define AUTOC_VALID_VALUE 1
198
+ #define AUTOC_VALID_KEY 2
199
+ #define AUTOC_OWNED_VALUE 4
200
+ #define AUTOC_OWNED_KEY 8
201
+ static #{@entry.type} #{entryKeyOnlyRef}(#{key.type}* key) {
202
+ #{@entry.type} entry;
203
+ entry.key = *key;
204
+ entry.flags = AUTOC_VALID_KEY;
205
+ return entry;
206
+ }
207
+ static #{@entry.type} #{entryKeyValueRef}(#{key.type}* key, #{value.type}* value) {
208
+ #{@entry.type} entry;
209
+ entry.key = *key;
210
+ entry.value = *value;
211
+ entry.flags = (AUTOC_VALID_KEY | AUTOC_VALID_VALUE);
212
+ return entry;
213
+ }
214
+ #define #{entryIdentify}(obj) #{entryIdentifyRef}(&obj)
215
+ static size_t #{entryIdentifyRef}(#{@entry.type}* entry) {
216
+ return #{key.identify("entry->key")};
217
+ }
218
+ #define #{entryEqual}(lt, rt) #{entryEqualRef}(&lt, &rt)
219
+ static int #{entryEqualRef}(#{@entry.type}* lt, #{@entry.type}* rt) {
220
+ return #{key.equal("lt->key", "rt->key")};
221
+ }
222
+ #define #{entryCopy}(dst, src) #{entryCopyRef}(&dst, &src)
223
+ static void #{entryCopyRef}(#{@entry.type}* dst, #{@entry.type}* src) {
224
+ #{assert}(src->flags & AUTOC_VALID_KEY);
225
+ dst->flags = (AUTOC_VALID_KEY | AUTOC_OWNED_KEY);
226
+ #{key.copy("dst->key", "src->key")};
227
+ if(src->flags & AUTOC_VALID_VALUE) {
228
+ dst->flags |= (AUTOC_VALID_VALUE | AUTOC_OWNED_VALUE);
229
+ #{value.copy("dst->value", "src->value")};
230
+ }
231
+ }
232
+ #define #{entryDtor}(obj) #{entryDtorRef}(&obj)
233
+ static void #{entryDtorRef}(#{@entry.type}* entry) {
234
+ #{assert}(entry->flags & AUTOC_VALID_KEY);
235
+ if(entry->flags & AUTOC_OWNED_KEY) #{key.dtor("entry->key")};
236
+ if(entry->flags & AUTOC_VALID_VALUE && entry->flags & AUTOC_OWNED_VALUE) #{value.dtor("entry->value")};
237
+ }
238
+ $
239
+ @set.write_exported_declarations(stream, static, inline)
240
+ @set.write_implementations(stream, static)
241
+ stream << %$
242
+ static #{@entry.type}* #{itGetEntryRef}(#{it}*);
243
+ #{define} void #{ctor}(#{type}* self) {
244
+ #{assert}(self);
245
+ #{@set.ctor}(&self->entries);
246
+ }
247
+ #{define} void #{dtor}(#{type}* self) {
248
+ #{assert}(self);
249
+ #{@set.dtor}(&self->entries);
250
+ }
251
+ static int #{putEntryRef}(#{type}* self, #{@entry.type}* entry) {
252
+ int absent;
253
+ #{assert}(self);
254
+ #{assert}(entry);
255
+ if((absent = !#{containsKey}(self, entry->key))) {
256
+ #{@set.put}(&self->entries, *entry);
257
+ }
258
+ return absent;
259
+ }
260
+ #{define} void #{copy}(#{type}* dst, #{type}* src) {
261
+ #{it} it;
262
+ #{assert}(src);
263
+ #{assert}(dst);
264
+ #{ctor}(dst);
265
+ #{itCtor}(&it, src);
266
+ while(#{itMove}(&it)) {
267
+ #{@entry.type}* e = #{itGetEntryRef}(&it);
268
+ #{putEntryRef}(dst, e);
269
+ }
270
+ }
271
+ static int #{containsAllOf}(#{type}* self, #{type}* other) {
272
+ #{it} it;
273
+ #{itCtor}(&it, self);
274
+ while(#{itMove}(&it)) {
275
+ int found = 0;
276
+ #{@entry.type}* e = #{itGetEntryRef}(&it);
277
+ if(#{containsKey}(other, e->key)) {
278
+ #{value.type} other_value = #{get}(other, e->key);
279
+ found = #{value.equal("e->value", "other_value")};
280
+ #{value.dtor("other_value")};
281
+ }
282
+ if(!found) return 0;
283
+ }
284
+ return 1;
285
+ }
286
+ #{define} int #{equal}(#{type}* lt, #{type}* rt) {
287
+ #{assert}(lt);
288
+ #{assert}(rt);
289
+ return #{size}(lt) == #{size}(rt) && #{containsAllOf}(lt, rt) && #{containsAllOf}(rt, lt);
290
+ }
291
+ #{define} size_t #{identify}(#{type}* self) {
292
+ #{assert}(self);
293
+ return #{@set.identify}(&self->entries); /* TODO : make use of the values' hashes */
294
+ }
295
+ #{define} void #{purge}(#{type}* self) {
296
+ #{assert}(self);
297
+ #{@set.purge}(&self->entries);
298
+ }
299
+ #{define} size_t #{size}(#{type}* self) {
300
+ #{assert}(self);
301
+ return #{@set.size}(&self->entries);
302
+ }
303
+ #{define} int #{containsKey}(#{type}* self, #{key.type} key) {
304
+ int result;
305
+ #{@entry.type} entry;
306
+ #{assert}(self);
307
+ result = #{@set.contains}(&self->entries, entry = #{entryKeyOnlyRef}(&key));
308
+ #{@entry.dtor("entry")};
309
+ return result;
310
+ }
311
+ #{define} #{value.type} #{get}(#{type}* self, #{key.type} key) {
312
+ #{value.type} result;
313
+ #{@entry.type} entry, existing_entry;
314
+ #{assert}(self);
315
+ #{assert}(#{containsKey}(self, key));
316
+ existing_entry = #{@set.get}(&self->entries, entry = #{entryKeyOnlyRef}(&key));
317
+ #{value.copy("result", "existing_entry.value")};
318
+ #{@entry.dtor("existing_entry")};
319
+ #{@entry.dtor("entry")};
320
+ return result;
321
+ }
322
+ #{define} int #{put}(#{type}* self, #{key.type} key, #{value.type} value) {
323
+ int result;
324
+ #{@entry.type} entry;
325
+ #{assert}(self);
326
+ entry = #{entryKeyValueRef}(&key, &value);
327
+ result = #{putEntryRef}(self, &entry);
328
+ #{@entry.dtor("entry")};
329
+ return result;
330
+ }
331
+ #{define} int #{replace}(#{type}* self, #{key.type} key, #{value.type} value) {
332
+ int result;
333
+ #{@entry.type} entry;
334
+ #{assert}(self);
335
+ entry = #{entryKeyValueRef}(&key, &value);
336
+ result = #{@set.replace}(&self->entries, entry);
337
+ #{@entry.dtor("entry")};
338
+ return result;
339
+ }
340
+ #{define} int #{remove}(#{type}* self, #{key.type} key) {
341
+ int result;
342
+ #{@entry.type} entry;
343
+ #{assert}(self);
344
+ result = #{@set.remove}(&self->entries, entry = #{entryKeyOnlyRef}(&key));
345
+ #{@entry.dtor("entry")};
346
+ return result;
347
+ }
348
+ #{define} void #{itCtor}(#{it}* self, #{type}* map) {
349
+ #{assert}(self);
350
+ #{assert}(map);
351
+ #{@set.itCtor}(&self->it, &map->entries);
352
+ }
353
+ #{define} int #{itMove}(#{it}* self) {
354
+ #{assert}(self);
355
+ return #{@set.itMove}(&self->it);
356
+ }
357
+ #{define} #{key.type} #{itGetKey}(#{it}* self) {
358
+ #{@entry.type}* e;
359
+ #{key.type} key;
360
+ #{assert}(self);
361
+ e = #{itGetEntryRef}(self);
362
+ #{key.copy("key", "e->key")};
363
+ return key;
364
+ }
365
+ #{define} #{value.type} #{itGetElement}(#{it}* self) {
366
+ #{@entry.type}* e;
367
+ #{value.type} value;
368
+ #{assert}(self);
369
+ e = #{itGetEntryRef}(self);
370
+ #{assert}(e->flags & AUTOC_VALID_VALUE);
371
+ #{value.copy("value", "e->value")};
372
+ return value;
373
+ }
374
+ static #{@entry.type}* #{itGetEntryRef}(#{it}* self) {
375
+ #{assert}(self);
376
+ return #{@set.itGetRef}(&self->it);
377
+ }
378
+ #undef AUTOC_VALID_VALUE
379
+ #undef AUTOC_VALID_KEY
380
+ #undef AUTOC_OWNED_VALUE
381
+ #undef AUTOC_OWNED_KEY
382
+ $
383
+ end
384
+
385
+ end # HashMap
386
+
387
+
388
+ end # AutoC