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,263 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ require 'autoc/ranges'
5
+ require 'autoc/sequential'
6
+ require 'autoc/association'
7
+
8
+
9
+ module AutoC
10
+
11
+
12
+ # Value type string wrapper of the plain C string
13
+ class CString < Association
14
+
15
+ include STD
16
+
17
+ include Sequential
18
+
19
+ def default_constructible? = false
20
+
21
+ def range = @range ||= Range.new(self, visibility: visibility, parallel: @parallel)
22
+
23
+ def initialize(type = :CString, char = :char, parallel: nil, **kws)
24
+ super(type, char, :size_t, **kws)
25
+ dependencies << STRING_H
26
+ @parallel = parallel
27
+ end
28
+
29
+ def rvalue = @rv ||= Value.new(self)
30
+
31
+ def lvalue = @lv ||= Value.new(self, reference: true)
32
+
33
+ def const_rvalue = @crv ||= Value.new(self, constant: true)
34
+
35
+ def const_lvalue = @clv ||= Value.new(self, reference: true, constant: true)
36
+
37
+ def render_interface(stream)
38
+ if public?
39
+ stream << %{
40
+ /**
41
+ #{defgroup}
42
+
43
+ @brief Value type wrapper of the plain C string
44
+
45
+ This type represents a (paper thin) wrapper around the plain C string (char *) with proper value semantics.
46
+
47
+ @since 2.0
48
+ */
49
+ }
50
+ else
51
+ stream << PRIVATE
52
+ end
53
+ stream << %{
54
+ typedef #{element.lvalue} #{signature};
55
+ }
56
+ end
57
+
58
+ def storage(target) = target # Return C pointer to contiguous storage
59
+
60
+ def render_forward_declarations(stream)
61
+ stream << %{
62
+ #include <stdio.h>
63
+ #include <malloc.h>
64
+ #include <stdarg.h>
65
+ /* overridable internal buffer size (in chars, not bytes) for *sprintf() operations */
66
+ #ifndef AUTOC_BUFFER_SIZE
67
+ #define AUTOC_BUFFER_SIZE 1024
68
+ #endif
69
+ }
70
+ super
71
+ end
72
+
73
+ def type_tag = "#{signature}<#{element}>"
74
+
75
+ private
76
+
77
+ def configure
78
+ super
79
+ method(:void, :create, { target: lvalue, source: const_rvalue }, instance: :custom_create).configure do
80
+ header %{
81
+ @brief Create string
82
+
83
+ @param[out] target string to be created
84
+ @param[in] source string to be copied
85
+
86
+ This function creates & initializes a new string by making an independent of the source string.
87
+ This specifically means that the supplied source string may be any C string, either const or mutable, including string literal.
88
+
89
+ Previous contents of `*target` is overwritten.
90
+
91
+ Once constructed, the string is to be destroyed with @ref #{destroy}.
92
+
93
+ @since 2.0
94
+ }
95
+ inline_code %{
96
+ size_t size;
97
+ assert(target);
98
+ assert(source);
99
+ size = strlen(source);
100
+ *target = #{memory.allocate(element, 'size+1', atomic: true)}; assert(*target);
101
+ memcpy(*target, source, size*sizeof(#{element}));
102
+ (*target)[size] = '\\0';
103
+ }
104
+ end
105
+ method(:int, :create_format, { target: lvalue, format: const_rvalue }, variadic: true ).configure do
106
+ code %{
107
+ int r;
108
+ va_list args;
109
+ #if defined(HAVE_VSNPRINTF) || __STDC_VERSION__ >= 199901L || __cplusplus > 199711L || (defined(_MSC_VER) && _MSC_VER >= 1900) || defined(__POCC__)
110
+ va_start(args, format);
111
+ r = vsnprintf(NULL, 0, format, args);
112
+ va_end(args);
113
+ if(r < 0) return 0;
114
+ *target = #{memory.allocate(element, 'r+1', atomic: true)}; assert(*target);
115
+ va_start(args, format);
116
+ r = vsnprintf(*target, r+1, format, args);
117
+ va_end(args);
118
+ return r >= 0;
119
+ #else
120
+ #if defined(_MSC_VER)
121
+ #pragma message("WARNING: this code employs bare sprintf() with preallocated temporary buffer of AUTOC_BUFFER_SIZE chars; expect execution bail outs upon exceeding this limit")
122
+ #else
123
+ #warning("this code employs bare sprintf() with preallocated temporary buffer of AUTOC_BUFFER_SIZE chars; expect execution bail outs upon exceeding this limit")
124
+ #endif
125
+ va_start(args, format);
126
+ #{element.lvalue} t = #{memory.allocate(element, :AUTOC_BUFFER_SIZE, atomic: true)}; assert(t);
127
+ r = vsprintf(t, format, args);
128
+ if(r >= 0) {
129
+ if(r > AUTOC_BUFFER_SIZE-1) {
130
+ /*
131
+ the output spilled out of the preallocated buffer -
132
+ perfer to bail out right away rather than to get likely heap corruption
133
+ */
134
+ abort();
135
+ }
136
+ /* prefer precision over performance and make a copy instead of returning a (possibly excessive) buffer */
137
+ #{default_create.(target, :t)};
138
+ }
139
+ /* FIXME handle the case of simultaneous (r < 0 && buffer overrun) */
140
+ #{memory.free(:t)};
141
+ va_end(args);
142
+ return r >= 0;
143
+ #endif
144
+ }
145
+ header %{
146
+ @brief Create formatted string
147
+
148
+ @param[out] target string to be created
149
+ @param[in] format format template
150
+ @param[in] ... format parameters
151
+
152
+ @result non-zero value on successful construction and zero value otherwise
153
+
154
+ This function employs a standard C function from the s*printf() family to create new formatted string.
155
+
156
+ @note No `*target` is modified on function failure.
157
+
158
+ @since 2.0
159
+ }
160
+ end
161
+ destroy.configure do
162
+ inline_code %{
163
+ assert(target);
164
+ #{memory.free('*target')};
165
+ }
166
+ end
167
+ copy.configure do
168
+ dependencies << custom_create
169
+ inline_code %{
170
+ #{custom_create.(*parameters)};
171
+ }
172
+ end
173
+ get.configure do
174
+ dependencies << check
175
+ inline_code %{
176
+ assert(target);
177
+ assert(#{check.(target, index)});
178
+ return target[index];
179
+ }
180
+ end
181
+ set.configure do
182
+ dependencies << check
183
+ inline_code %{
184
+ assert(target);
185
+ assert(#{check.(target, index)});
186
+ target[index] = value;
187
+ }
188
+ end
189
+ view.configure do
190
+ dependencies << check
191
+ inline_code %{
192
+ assert(target);
193
+ assert(#{check.(target, index)});
194
+ return &target[index];
195
+ }
196
+ end
197
+ equal.configure do
198
+ inline_code %{
199
+ assert(left);
200
+ assert(right);
201
+ return strcmp(left, right) == 0;
202
+ }
203
+ end
204
+ compare.configure do
205
+ inline_code %{
206
+ assert(left);
207
+ assert(right);
208
+ return strcmp(left, right);
209
+ }
210
+ end
211
+ hash_code.configure do
212
+ code %{
213
+ /* djb2 algorithm: http://www.cse.yorku.ca/~oz/hash.html */
214
+ size_t c;
215
+ size_t hash;
216
+ #{element.lvalue} s;
217
+ assert(target);
218
+ hash = 5381;
219
+ s = target;
220
+ while((c = *s++)) hash = hash*33 ^ c;
221
+ return hash;
222
+ }
223
+ end
224
+ contains.configure do
225
+ inline_code %{
226
+ assert(target);
227
+ return strchr(target, value) != NULL;
228
+ }
229
+ end
230
+ find_first.configure do
231
+ inline_code %{
232
+ assert(target);
233
+ return strchr(target, value);
234
+ }
235
+ end
236
+ check.configure do
237
+ dependencies << size
238
+ inline_code %{
239
+ assert(target);
240
+ return index < #{size.(target)};
241
+ }
242
+ end
243
+ empty.configure do
244
+ inline_code %{
245
+ assert(target);
246
+ return *target == '\\0';
247
+ }
248
+ end
249
+ size.configure do
250
+ inline_code %{
251
+ assert(target);
252
+ return strlen(target);
253
+ }
254
+ end
255
+ end
256
+
257
+ end # CString
258
+
259
+
260
+ CString::Range = ContiguousRange # Range
261
+
262
+
263
+ end
@@ -0,0 +1,247 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ require 'autoc/type'
5
+ require 'autoc/module'
6
+ require 'autoc/primitive'
7
+
8
+
9
+ module AutoC
10
+
11
+
12
+ # @private
13
+ class Value
14
+
15
+ attr_reader :type
16
+
17
+ def to_type = type
18
+
19
+ def to_value = self
20
+
21
+ def constant? = @constant == true
22
+
23
+ def reference? = @reference == true
24
+
25
+ def initialize(type, constant: false, reference: false)
26
+ @type = type
27
+ @constant = constant
28
+ @reference = reference
29
+ end
30
+
31
+ def to_s = signature
32
+
33
+ def signature
34
+ _ = reference? ? "#{type.signature}*" : type.signature
35
+ constant? ? "const #{_}" : _
36
+ end
37
+
38
+ def call(value)
39
+ value = value.to_s
40
+ if reference?
41
+ # Manually collapse references &*xyz -> xyz for the sake of source code readability
42
+ value[0] =='*' ? value[1..-1] : "&#{value}"
43
+ else
44
+ value
45
+ end
46
+ end
47
+ end # Value
48
+
49
+
50
+ # @private
51
+ # Function parameter
52
+ class Parameter
53
+
54
+ attr_reader :value
55
+
56
+ attr_reader :name
57
+
58
+ def initialize(value, name)
59
+ @value = value.to_value
60
+ @name = name.to_sym
61
+ end
62
+
63
+ def to_s = name.to_s
64
+
65
+ def to_value_argument = value.reference? ? "*#{name}" : name
66
+
67
+ def signature = value.signature
68
+
69
+ def declaration = '%s %s' % [signature, name]
70
+
71
+ end # Parameter
72
+
73
+
74
+ # Standalone C side function
75
+ # The generated function is meant to be the C89-compliant
76
+ # NOTE: This function does not track parameter and result types as its dependencies
77
+ # This can be done manually by appending to #dependencies property with <<
78
+ class Function
79
+
80
+ include Entity
81
+
82
+ attr_reader :name
83
+
84
+ attr_reader :result
85
+
86
+ attr_reader :parameters
87
+
88
+ attr_reader :visibility
89
+
90
+ attr_writer :inline
91
+
92
+ def initialize(result, name, parameters, inline: false, visibility: :public, constraint: true, variadic: false, abstract: false)
93
+ @name = name.to_s
94
+ @result = result
95
+ @inline = inline
96
+ @visibility = visibility
97
+ @constraint = constraint
98
+ @abstract = abstract
99
+ @variadic = variadic
100
+ @parameters = Parameters.new(self)
101
+ if parameters.is_a?(Hash)
102
+ parameters.each do |name, descriptor|
103
+ x = Parameter.new(descriptor, name)
104
+ @parameters[x.name] = x
105
+ end
106
+ else
107
+ i = -1
108
+ parameters.each do |descriptor|
109
+ x = Parameter.new(descriptor, "_#{i+=1}")
110
+ @parameters[x.name] = x
111
+ end
112
+ end
113
+ end
114
+
115
+ def inline_code(code)
116
+ @inline = true
117
+ code(code)
118
+ end
119
+
120
+ def external_code(code)
121
+ @inline = false
122
+ code(code)
123
+ end
124
+
125
+ def to_s = name
126
+
127
+ def header(header) = @header = header
128
+
129
+ def code(code) = @code = code
130
+
131
+ def inspect = "#{prototype} <#{self.class}>"
132
+
133
+ def inline? = @inline == true
134
+
135
+ def public? = @visibility == :public
136
+
137
+ def abstract? = @abstract == true
138
+
139
+ def variadic? = @variadic == true
140
+
141
+ def live? = (@constraint.is_a?(Proc) ? @constraint.() : @constraint) == true
142
+
143
+ def signature = '%s(%s)' % [result.signature, (parameters.to_a.collect(&:signature) << (variadic? ? '...' : nil)).compact.join(',')]
144
+
145
+ def prototype = '%s %s(%s)' % [result.signature, name, (parameters.to_a.collect(&:declaration) << (variadic? ? '...' : nil)).compact.join(',')]
146
+
147
+ def definition = '%s {%s}' % [prototype, @code]
148
+
149
+ def parameter(name) = @values[name]
150
+
151
+ def call(*arguments)
152
+ xs = []
153
+ ps = parameters.to_a
154
+ (0...arguments.size).each do |i|
155
+ a = arguments[i]
156
+ v = a.is_a?(Parameter) ? a.to_value_argument : a
157
+ xs << (i < ps.size ? ps[i].value.(v) : v)
158
+ end
159
+ '%s(%s)' % [name, xs.join(',')]
160
+ end
161
+
162
+ def configure(&block)
163
+ instance_eval(&block)
164
+ self
165
+ end
166
+
167
+ # This allows to call other functions with this function's individual parameters as arguments
168
+ # A call to unknown method results in the method's name being emitted
169
+ def method_missing(meth, *args) = parameters.has_key?(meth) ? parameters[meth] : meth
170
+
171
+ private
172
+
173
+ # On function inlining in C: http://www.greenend.org.uk/rjk/tech/inline.html
174
+
175
+ # static inline seems to be THE most portable way without resorting to preprocessor
176
+ # but consider the possible code bloat it incurs
177
+
178
+ def render_declaration_specifier(stream)
179
+ # The inline specifier is not a part of C89 yet descent compilers do inlining at will
180
+ # given the function definition is available at the function call
181
+ stream << 'static ' if inline?
182
+ end
183
+
184
+ # Render the commentary block preceding the function declaration, both inline or external
185
+ def render_function_header(stream)
186
+ stream << %{
187
+ /* #{@header} */
188
+ } unless @header.nil?
189
+ end
190
+
191
+ # Render full function declaration statement including the commentary block
192
+ # For inline functions this also renders a function body effectively making this also a function definition
193
+ # The declaration comes into either public interface of forward declaration block depending on the function's visibility status
194
+ def render_function_declaration(stream)
195
+ render_function_header(stream)
196
+ render_declaration_specifier(stream)
197
+ if inline?
198
+ render_function_definition(stream)
199
+ else
200
+ stream << prototype << ';'
201
+ end
202
+ end
203
+
204
+ # Render function definition, both inline or extern
205
+ # This code never gets into public interface
206
+ def render_function_definition(stream)
207
+ unless abstract?
208
+ raise("missing function definition for #{name}()") if @code.nil?
209
+ stream << definition
210
+ end
211
+ end
212
+
213
+ # Render function's public interface
214
+ # Only public functions are rendered
215
+ def render_interface(stream)
216
+ render_function_declaration(stream) if live? && public?
217
+ end
218
+
219
+ # Render function's interface for non-public functions which should not appear in the public interface
220
+ def render_forward_declarations(stream)
221
+ render_function_declaration(stream) if live? && !public?
222
+ end
223
+
224
+ # Render non-inline function definition regardless of function's visibility status
225
+ def render_implementation(stream)
226
+ render_function_definition(stream) if live? && !inline?
227
+ end
228
+
229
+ end # Function
230
+
231
+
232
+ # @private
233
+ # Named parameter list for the function
234
+ class Function::Parameters < ::Hash
235
+ def initialize(function)
236
+ @function = function
237
+ super()
238
+ end
239
+ def to_a = values
240
+ def [](name)
241
+ raise "unknown parameter #{name} in function #{@function}()" unless has_key?(name)
242
+ super
243
+ end
244
+ end # Parameters
245
+
246
+
247
+ end