autoc 1.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +3 -0
  3. data/README.md +149 -0
  4. data/cmake/AutoC.cmake +39 -0
  5. data/lib/autoc/allocators.rb +51 -0
  6. data/lib/autoc/association.rb +126 -0
  7. data/lib/autoc/box.rb +311 -0
  8. data/lib/autoc/cmake.rb +54 -0
  9. data/lib/autoc/collection.rb +83 -110
  10. data/lib/autoc/composite.rb +333 -0
  11. data/lib/autoc/cstring.rb +263 -0
  12. data/lib/autoc/function.rb +247 -0
  13. data/lib/autoc/hash_map.rb +328 -0
  14. data/lib/autoc/hash_set.rb +339 -0
  15. data/lib/autoc/hashers.rb +102 -0
  16. data/lib/autoc/list.rb +444 -0
  17. data/lib/autoc/module.rb +434 -0
  18. data/lib/autoc/openmp.rb +15 -0
  19. data/lib/autoc/primitive.rb +27 -0
  20. data/lib/autoc/ranges.rb +707 -0
  21. data/lib/autoc/record.rb +247 -0
  22. data/lib/autoc/scaffold/docs.rb +117 -0
  23. data/lib/autoc/scaffold/generic_value.rb +86 -0
  24. data/lib/autoc/scaffold/project.rb +75 -0
  25. data/lib/autoc/scaffold/test_cstring.rb +113 -0
  26. data/lib/autoc/scaffold/test_cstring_hash_set.rb +35 -0
  27. data/lib/autoc/scaffold/test_int_box.rb +22 -0
  28. data/lib/autoc/scaffold/test_int_hash_set.rb +448 -0
  29. data/lib/autoc/scaffold/test_int_list.rb +106 -0
  30. data/lib/autoc/scaffold/test_int_vector.rb +83 -0
  31. data/lib/autoc/scaffold/test_v2v_hash_map.rb +83 -0
  32. data/lib/autoc/scaffold/test_value_hash_set.rb +60 -0
  33. data/lib/autoc/scaffold/test_value_vector.rb +146 -0
  34. data/{test/test.rb → lib/autoc/scaffold/tests.rb} +179 -158
  35. data/lib/autoc/scaffold.rb +12 -0
  36. data/lib/autoc/sequential.rb +99 -0
  37. data/lib/autoc/set.rb +331 -0
  38. data/lib/autoc/std.rb +149 -0
  39. data/lib/autoc/type.rb +93 -531
  40. data/lib/autoc/vector.rb +290 -0
  41. data/lib/autoc.rb +4 -35
  42. metadata +55 -85
  43. data/.yardopts +0 -4
  44. data/CHANGES +0 -23
  45. data/README +0 -28
  46. data/doc/AutoC/Code.html +0 -523
  47. data/doc/AutoC/Collection.html +0 -1214
  48. data/doc/AutoC/HashMap.html +0 -1441
  49. data/doc/AutoC/HashSet.html +0 -916
  50. data/doc/AutoC/Iterators/Bidirectional.html +0 -204
  51. data/doc/AutoC/Iterators/Unidirectional.html +0 -200
  52. data/doc/AutoC/Iterators.html +0 -126
  53. data/doc/AutoC/List.html +0 -1039
  54. data/doc/AutoC/Maps.html +0 -290
  55. data/doc/AutoC/Module/File.html +0 -415
  56. data/doc/AutoC/Module/Header.html +0 -437
  57. data/doc/AutoC/Module/Source.html +0 -707
  58. data/doc/AutoC/Module.html +0 -948
  59. data/doc/AutoC/Priority.html +0 -138
  60. data/doc/AutoC/Queue.html +0 -1172
  61. data/doc/AutoC/Reference.html +0 -735
  62. data/doc/AutoC/Sets.html +0 -520
  63. data/doc/AutoC/String.html +0 -1394
  64. data/doc/AutoC/TreeMap.html +0 -1565
  65. data/doc/AutoC/TreeSet.html +0 -1447
  66. data/doc/AutoC/Type.html +0 -2148
  67. data/doc/AutoC/UserDefinedType.html +0 -1047
  68. data/doc/AutoC/Vector.html +0 -987
  69. data/doc/AutoC.html +0 -331
  70. data/doc/_index.html +0 -388
  71. data/doc/class_list.html +0 -51
  72. data/doc/css/common.css +0 -1
  73. data/doc/css/full_list.css +0 -58
  74. data/doc/css/style.css +0 -481
  75. data/doc/file.CHANGES.html +0 -117
  76. data/doc/file.README.html +0 -116
  77. data/doc/file_list.html +0 -61
  78. data/doc/frames.html +0 -17
  79. data/doc/index.html +0 -116
  80. data/doc/js/app.js +0 -243
  81. data/doc/js/full_list.js +0 -216
  82. data/doc/js/jquery.js +0 -4
  83. data/doc/method_list.html +0 -1307
  84. data/doc/top-level-namespace.html +0 -112
  85. data/lib/autoc/code.rb +0 -237
  86. data/lib/autoc/collection/hash_map.rb +0 -385
  87. data/lib/autoc/collection/hash_set.rb +0 -337
  88. data/lib/autoc/collection/iterator.rb +0 -39
  89. data/lib/autoc/collection/list.rb +0 -429
  90. data/lib/autoc/collection/map.rb +0 -41
  91. data/lib/autoc/collection/queue.rb +0 -517
  92. data/lib/autoc/collection/set.rb +0 -134
  93. data/lib/autoc/collection/tree_map.rb +0 -464
  94. data/lib/autoc/collection/tree_set.rb +0 -611
  95. data/lib/autoc/collection/vector.rb +0 -336
  96. data/lib/autoc/string.rb +0 -492
  97. data/test/test_auto.c +0 -7141
  98. data/test/test_auto.h +0 -753
  99. data/test/test_char_string.rb +0 -270
  100. data/test/test_int_list.rb +0 -35
  101. data/test/test_int_tree_set.rb +0 -111
  102. data/test/test_int_vector.rb +0 -34
  103. data/test/test_value_hash_map.rb +0 -162
  104. data/test/test_value_hash_set.rb +0 -173
  105. data/test/test_value_list.rb +0 -193
  106. data/test/test_value_queue.rb +0 -275
  107. data/test/test_value_tree_map.rb +0 -176
  108. data/test/test_value_tree_set.rb +0 -173
  109. data/test/test_value_vector.rb +0 -155
  110. data/test/value.rb +0 -80
@@ -0,0 +1,102 @@
1
+ require 'singleton'
2
+ require 'autoc/std'
3
+ require 'autoc/module'
4
+
5
+
6
+ module AutoC
7
+
8
+
9
+ # Basic xor-shift incremental hasher
10
+ class Hasher
11
+
12
+ include STD
13
+
14
+ include Singleton
15
+
16
+ include Entity
17
+
18
+ def to_s = :size_t
19
+
20
+ def create(hasher) = "#{hasher} = AUTOC_HASHER_SEED"
21
+
22
+ def destroy(hasher) = nil
23
+
24
+ def update(hasher, value) = "#{hasher} = ((#{hasher} << 1) | (#{hasher} >> (sizeof(#{hasher})*CHAR_BIT - 1))) ^ (#{value})"
25
+
26
+ def result(hasher) = hasher
27
+
28
+ def initialize = dependencies << STDLIB_H
29
+
30
+ def render_forward_declarations(stream)
31
+ stream << %{
32
+ #include <limits.h>
33
+ #include <stddef.h>
34
+ #ifndef AUTOC_HASHER_SEED /* no seed is specified, using randomly generated one */
35
+ #define _AUTOC_RANDOMIZE_SEED
36
+ #define AUTOC_HASHER_SEED _autoc_hasher_seed
37
+ AUTOC_EXTERN void
38
+ #ifdef __POCC__
39
+ __cdecl
40
+ #endif
41
+ _autoc_hasher_randomize_seed(void); /* invoke default seed randomizer */
42
+ AUTOC_EXTERN size_t _autoc_hasher_seed;
43
+ #elif ~(~AUTOC_HASHER_SEED + 1) == 1 /* if macro value is unspecified on the command line it is implicitly set to 1 */
44
+ #undef AUTOC_HASHER_SEED
45
+ #define AUTOC_HASHER_SEED 0 /* set seed's default value */
46
+ #endif
47
+ }
48
+ end
49
+
50
+ def render_implementation(stream)
51
+ # Predefined C compiler macros datasheet: https://sourceforge.net/p/predef/wiki/Compilers/
52
+ stream << %{
53
+ #ifdef _AUTOC_RANDOMIZE_SEED
54
+ size_t _autoc_hasher_seed = 0; /* fallback default until _autoc_hasher_randomize_seed() is called */
55
+ #if defined(__cplusplus)
56
+ extern "C" void _autoc_hasher_randomize_seed(void);
57
+ #elif defined(__GNUC__) || defined(__clang__)
58
+ void _autoc_hasher_randomize_seed(void) __attribute__((__constructor__));
59
+ #elif defined(__POCC__)
60
+ #pragma startup _autoc_hasher_randomize_seed
61
+ #elif defined(_MSC_VER) || defined(__POCC__)
62
+ #pragma message("WARNING: _autoc_hasher_randomize_seed() will not be called automatically; either call it manually or compile this source as C++ in order to actually yield random seed")
63
+ #else
64
+ #warning _autoc_hasher_randomize_seed() will not be be called automatically; either call it manually or compile this source as C++ in order to actually yield random seed
65
+ #endif
66
+ #include <time.h>
67
+ #ifdef __POCC__
68
+ #include <stdlib.h>
69
+ #endif
70
+ void
71
+ #ifdef __POCC__
72
+ __cdecl
73
+ #endif
74
+ _autoc_hasher_randomize_seed(void) {
75
+ #if defined(__POCC__)
76
+ /* Pelles C check comes first as it might set _MSC_VER as well */
77
+ unsigned r;
78
+ _rand_s(&r);
79
+ _autoc_hasher_seed = r;
80
+ #elif defined(_MSC_VER)
81
+ unsigned r;
82
+ rand_s(&r);
83
+ _autoc_hasher_seed = r;
84
+ #else
85
+ srand(time(NULL));
86
+ _autoc_hasher_seed = rand();
87
+ #endif
88
+ }
89
+ #ifdef __cplusplus
90
+ static struct _hasher {
91
+ _hasher() {_autoc_hasher_randomize_seed();}
92
+ } _hasher;
93
+ #endif
94
+
95
+ #endif
96
+ }
97
+ end
98
+
99
+ end # Hasher
100
+
101
+
102
+ end
data/lib/autoc/list.rb ADDED
@@ -0,0 +1,444 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ require 'autoc/ranges'
5
+ require 'autoc/sequential'
6
+ require 'autoc/collection'
7
+
8
+
9
+ module AutoC
10
+
11
+
12
+ using STD::Coercions
13
+
14
+
15
+ # Generator for singly linked collection of elements
16
+ class List < Collection
17
+
18
+ include Sequential
19
+
20
+ def _range_class = Range
21
+
22
+ def range = @range ||= _range_class.new(self, visibility: visibility)
23
+
24
+ attr_reader :_node, :_node_p, :_node_pp
25
+
26
+ # maintain_size:
27
+ # true: managed size field (extra memory consumption)
28
+ # false: computing #size function (slow, O(N))
29
+ def initialize(*args, maintain_size: true, **kws)
30
+ super(*args, **kws)
31
+ @_node = identifier(:_node, abbreviate: true)
32
+ @_node_p = _node.lvalue
33
+ @_node_pp = "#{_node}*".lvalue
34
+ @maintain_size = maintain_size
35
+ end
36
+
37
+ def maintain_size? = @maintain_size
38
+
39
+ def render_interface(stream)
40
+ stream << %{
41
+ /** @private */
42
+ typedef struct #{_node} #{_node};
43
+ }
44
+ if public?
45
+ stream << %{
46
+ /**
47
+ #{defgroup}
48
+
49
+ @brief Singly linked list of elements of type #{element}
50
+
51
+ For iteration over the list elements refer to @ref #{range}.
52
+
53
+ @see C++ [std::forward_list<T>](https://en.cppreference.com/w/cpp/container/forward_list)
54
+
55
+ @since 2.0
56
+ */
57
+ }
58
+ stream << %{
59
+ /**
60
+ #{ingroup}
61
+
62
+ @brief Opaque structure holding state of the list
63
+
64
+ @since 2.0
65
+ */
66
+ }
67
+ else
68
+ stream << PRIVATE
69
+ end
70
+ stream << %{
71
+ typedef struct {
72
+ #{_node_p} front; /**< @private */
73
+ #{'size_t size; /**< @private */' if maintain_size?}
74
+ } #{signature};
75
+ /** @private */
76
+ struct #{_node} {
77
+ #{element} element;
78
+ #{_node_p} next;
79
+ };
80
+ }
81
+ end
82
+
83
+ private
84
+
85
+ def configure
86
+ super
87
+ method(:int, :_replace_first, { target: rvalue, value: element.const_rvalue }, visibility: :internal, constraint:-> { element.copyable? }).configure do
88
+ # Replace first found element with specified value in-place
89
+ code %{
90
+ #{element.lvalue} e = (#{element.lvalue})#{find_first.(target, value)};
91
+ if(e) {
92
+ #{element.destroy.('*e') if element.destructible?};
93
+ #{element.copy.('*e', value)};
94
+ return 1;
95
+ } else
96
+ return 0;
97
+ }
98
+ end
99
+ # Code template for locating the list node satisfying custom equality condition
100
+ def _locate_node_equal(eq)
101
+ %{
102
+ #{_node_p} curr;
103
+ #{_node_p} prev;
104
+ assert(target);
105
+ assert(prev_p);
106
+ assert(curr_p);
107
+ prev = NULL;
108
+ curr = target->front;
109
+ while(curr) {
110
+ if(#{eq}) {
111
+ #ifndef NDEBUG
112
+ if(prev)
113
+ assert(prev->next == curr);
114
+ else
115
+ assert(target->front == curr);
116
+ #endif
117
+ *prev_p = prev;
118
+ *curr_p = curr;
119
+ return 1;
120
+ }
121
+ prev = curr;
122
+ curr = curr->next;
123
+ }
124
+ return 0;
125
+ }
126
+ end
127
+ method(:int, :_locate_node, { target: const_rvalue, value: element.const_rvalue, prev_p: _node_pp, curr_p: _node_pp }, visibility: :internal, constraint:-> { element.comparable? }).configure do
128
+ # Locate node satisfying default element equality condition, return this and previous nodes
129
+ code _locate_node_equal(element.equal.('curr->element', value))
130
+ end
131
+ method(:void, :_pop_front, { target: rvalue }, visibility: :internal).configure do
132
+ # Destroy frontal node but keep the element intact
133
+ code %{
134
+ #{_node_p} curr;
135
+ assert(!#{empty.(target)});
136
+ curr = target->front; assert(curr);
137
+ target->front = target->front->next;
138
+ #{'--target->size;' if maintain_size?}
139
+ #{memory.free(:curr)};
140
+ }
141
+ end
142
+ method(_node_p, :_pull_node, { target: rvalue }, visibility: :internal).configure do
143
+ # Cut & return frontal node
144
+ code %{
145
+ #{_node_p} curr;
146
+ assert(!#{empty.(target)});
147
+ curr = target->front; assert(curr);
148
+ target->front = curr->next;
149
+ #{'--target->size;' if maintain_size?}
150
+ return curr;
151
+ }
152
+ end
153
+ method(:void, :_push_node, { target: rvalue, curr: _node_p }, visibility: :internal).configure do
154
+ # Push exising node with intact payload
155
+ code %{
156
+ assert(target);
157
+ curr->next = target->front;
158
+ target->front = curr;
159
+ #{'++target->size;' if maintain_size?}
160
+ }
161
+ end
162
+ method(element.const_lvalue, :view_front, { target: const_rvalue })
163
+ method(element, :take_front, { target: const_rvalue }, constraint:-> { element.copyable? })
164
+ view_front.configure do
165
+ dependencies << empty
166
+ inline_code %{
167
+ assert(!#{empty.(target)});
168
+ return &(target->front->element);
169
+ }
170
+ header %{
171
+ @brief Get a view of the front element
172
+
173
+ @param[in] target list to get element from
174
+ @return a view of a front element
175
+
176
+ This function is used to get a constant reference (in form of the C pointer) to the front value contained in `target`.
177
+ Refer to @ref #{take_front} to get an independent copy of that element.
178
+
179
+ It is generally not safe to bypass the constness and to alter the value in place (although no one prevents to).
180
+
181
+ @note List must not be empty (see @ref #{empty}).
182
+
183
+ @since 2.0
184
+ }
185
+ end
186
+ take_front.configure do
187
+ code %{
188
+ #{element} result;
189
+ #{element.const_lvalue} e;
190
+ assert(target);
191
+ assert(!#{empty.(target)});
192
+ e = #{view_front.(target)};
193
+ #{element.copy.(:result, '*e')};
194
+ return result;
195
+ }
196
+ header %{
197
+ @brief Get front element
198
+
199
+ @param[in] target list to get element from
200
+ @return a *copy* of a front element
201
+
202
+ This function is used to get a *copy* of the front value contained in `target`.
203
+ Refer to @ref #{view_front} to get a view of that element without making an independent copy.
204
+
205
+ This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation).
206
+
207
+ @note List must not be empty (see @ref #{empty}).
208
+
209
+ @since 2.0
210
+ }
211
+ end
212
+ method(element, :pull_front, { target: rvalue }).configure do
213
+ code %{
214
+ #{element} result;
215
+ assert(target);
216
+ assert(!#{empty.(target)});
217
+ result = *#{view_front.(target)};
218
+ #{_pop_front.(target)};
219
+ return result;
220
+ }
221
+ header %{
222
+ @brief Extract front element
223
+
224
+ @param[in] target list to extract element from
225
+ @return front element
226
+
227
+ This function removes front element from the list and returns it.
228
+ Note that contrary to @ref #{take_front} no copy operation is performed - it is the contained value itself that is returned.
229
+
230
+ @note List must not be empty (see @ref #{empty}).
231
+
232
+ @since 2.0
233
+ }
234
+ end
235
+ method(:void, :drop_front, { target: rvalue }).configure do
236
+ if element.destructible?
237
+ code %{
238
+ #{element.lvalue} e;
239
+ assert(target);
240
+ assert(!#{empty.(target)});
241
+ e = (#{element.lvalue})#{view_front.(target)};
242
+ #{element.destroy.('*e')};
243
+ #{_pop_front.(target)};
244
+ }
245
+ else
246
+ code %{
247
+ assert(target);
248
+ assert(!#{empty.(target)});
249
+ #{_pop_front.(target)};
250
+ }
251
+ end
252
+ header %{
253
+ @brief Drop front element
254
+
255
+ @param[in] target list to drop element from
256
+
257
+ This function removes front element from the list and destroys it with the respective destructor.
258
+
259
+ @note List must not be empty (see @ref #{empty}).
260
+
261
+ @since 2.0
262
+ }
263
+ end
264
+ method(:void, :push_front, { target: rvalue, value: element.const_rvalue }, constraint:-> { element.copyable? }).configure do
265
+ code %{
266
+ #{_node_p} curr;
267
+ assert(target);
268
+ curr = #{memory.allocate(_node)};
269
+ curr->next = target->front;
270
+ target->front = curr;
271
+ #{'++target->size;' if maintain_size?}
272
+ #{element.copy.('curr->element', value)};
273
+ }
274
+ header %{
275
+ @brief Put element
276
+
277
+ @param[in] target vector to put element into
278
+ @param[in] value value to put
279
+
280
+ This function pushes a *copy* of the specified value to the front position of `target`.
281
+ It becomes a new front element.
282
+
283
+ This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation).
284
+
285
+ @since 2.0
286
+ }
287
+ end
288
+ def _remove_first(locator)
289
+ %{
290
+ #{_node_p} curr;
291
+ #{_node_p} prev;
292
+ assert(target);
293
+ if(#{locator}) {
294
+ assert(curr);
295
+ if(prev) {
296
+ prev->next = curr->next;
297
+ } else {
298
+ target->front = curr->next;
299
+ }
300
+ #{element.destroy.('curr->element') if element.destructible?};
301
+ #{memory.free(:curr)};
302
+ #{'--target->size;' if maintain_size?}
303
+ return 1;
304
+ }
305
+ return 0;
306
+ }
307
+ end
308
+ method(:int, :remove_first, { target: rvalue, value: element.const_rvalue }, constraint:-> { element.comparable? }).configure do
309
+ code _remove_first(_locate_node.(target, value, :prev, :curr))
310
+ header %{
311
+ @brief Remove element
312
+
313
+ @param[in] target list to remove element from
314
+ @param[in] value value to search in list
315
+ @return non-zero value on successful removal and zero value otherwise
316
+
317
+ This function searches `target` for a first element equal to the specified `value` and removes it from the list.
318
+ The removed element is destroyed with respective destructor.
319
+
320
+ The function return value is non-zero if such element was found and removed and zero value otherwise.
321
+
322
+ This function requires the element type to be *comparable* (i.e. to have a well-defined equality operation).
323
+
324
+ @since 2.0
325
+ }
326
+ end
327
+ default_create.configure do
328
+ inline_code %{
329
+ assert(target);
330
+ target->front = NULL;
331
+ #{'target->size = 0;' if maintain_size?}
332
+ }
333
+ end
334
+ destroy.configure do
335
+ code %{
336
+ assert(target);
337
+ while(!#{empty.(target)}) #{drop_front.(target)};
338
+ }
339
+ end
340
+ copy.configure do
341
+ code %{
342
+ size_t i;
343
+ #{range} r;
344
+ #{element.const_lvalue}* t;
345
+ assert(target);
346
+ assert(source);
347
+ #{default_create.(target)};
348
+ t = #{memory.allocate(element.const_lvalue, size.(source))};
349
+ for(i = 0, r = #{range.new.(source)}; !#{range.empty.(:r)}; #{range.pop_front.(:r)}) {
350
+ t[i++] = #{range.view_front.(:r)};
351
+ }
352
+ while(i > 0) #{push_front.(target, '*t[(i--)-1]')}; /* put elements in reverse order since the list itself is a LIFO structure */
353
+ #{memory.free(:t)};
354
+ }
355
+ end
356
+ empty.configure do
357
+ inline_code %{
358
+ assert(target);
359
+ return target->front == NULL;
360
+ }
361
+ end
362
+ if maintain_size?
363
+ size.configure do
364
+ inline_code %{
365
+ assert(target);
366
+ return target->size;
367
+ }
368
+ end
369
+ else
370
+ size.configure do
371
+ code %{
372
+ #{range} r;
373
+ size_t size;
374
+ assert(target);
375
+ for(size = 0, r = #{range.new.(target)}; !#{range.empty.(:r)}; ++size, #{range.pop_front.(:r)});
376
+ return size;
377
+ }
378
+ end
379
+ end
380
+ end
381
+ end # List
382
+
383
+
384
+ class List::Range < ForwardRange
385
+
386
+ def render_interface(stream)
387
+ if public?
388
+ render_type_description(stream)
389
+ stream << %{
390
+ /**
391
+ #{ingroup}
392
+ @brief Opaque structure holding state of the list's range
393
+ @since 2.0
394
+ */
395
+ }
396
+ else
397
+ stream << PRIVATE
398
+ end
399
+ stream << %{
400
+ typedef struct {
401
+ #{iterable._node_p} front; /**< @private */
402
+ } #{signature};
403
+ }
404
+ end
405
+
406
+ private
407
+
408
+ def configure
409
+ super
410
+ custom_create.configure do
411
+ inline_code %{
412
+ assert(range);
413
+ assert(iterable);
414
+ range->front = iterable->front;
415
+ }
416
+ end
417
+ empty.configure do
418
+ inline_code %{
419
+ assert(range);
420
+ return range->front == NULL;
421
+ }
422
+ end
423
+ pop_front.configure do
424
+ dependencies << empty
425
+ inline_code %{
426
+ assert(range);
427
+ assert(!#{empty.(range)});
428
+ range->front = range->front->next;
429
+ }
430
+ end
431
+ view_front.configure do
432
+ dependencies << empty
433
+ inline_code %{
434
+ assert(range);
435
+ assert(!#{empty.(range)});
436
+ return &range->front->element;
437
+ }
438
+ end
439
+ end
440
+
441
+ end # List
442
+
443
+
444
+ end