autoc 1.4 → 2.0.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 (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