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,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