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.
- checksums.yaml +7 -0
- data/README +15 -4
- data/doc/AutoC.html +245 -0
- data/doc/AutoC/Code.html +520 -0
- data/doc/AutoC/Collection.html +923 -0
- data/doc/AutoC/HashMap.html +1161 -0
- data/doc/AutoC/HashSet.html +1122 -0
- data/doc/AutoC/List.html +1002 -0
- data/doc/AutoC/Module.html +951 -0
- data/doc/AutoC/Module/File.html +412 -0
- data/doc/AutoC/Module/Header.html +432 -0
- data/doc/AutoC/Module/Source.html +704 -0
- data/doc/AutoC/Priority.html +138 -0
- data/doc/AutoC/Queue.html +1167 -0
- data/doc/AutoC/Type.html +1152 -0
- data/doc/AutoC/UserDefinedType.html +655 -0
- data/doc/AutoC/Vector.html +856 -0
- data/doc/_index.html +299 -0
- data/doc/class_list.html +54 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +339 -0
- data/doc/file.README.html +112 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +26 -0
- data/doc/index.html +112 -0
- data/doc/js/app.js +219 -0
- data/doc/js/full_list.js +178 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +605 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/autoc.rb +35 -12
- data/lib/autoc/{code_builder.rb → code.rb} +230 -247
- data/lib/autoc/collection.rb +137 -0
- data/lib/autoc/collection/hash_map.rb +388 -0
- data/lib/autoc/collection/hash_set.rb +433 -0
- data/lib/autoc/collection/list.rb +410 -0
- data/lib/autoc/collection/queue.rb +514 -0
- data/lib/autoc/collection/vector.rb +295 -0
- data/lib/autoc/type.rb +198 -0
- data/test/test.c +921 -396
- data/test/test.h +41 -0
- data/test/test.rb +21 -26
- data/test/test_auto.c +2630 -3961
- data/test/test_auto.h +449 -560
- metadata +50 -17
- data/lib/autoc/data_struct_builder.rb +0 -1794
- data/lib/autoc/type_builder.rb +0 -24
- data/manual/manual.pdf +0 -0
metadata
CHANGED
@@ -1,31 +1,64 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: autoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0
|
5
|
-
prerelease:
|
4
|
+
version: '1.0'
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Oleg A. Khlybov
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-06-06 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
|
-
description:
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
description: |2
|
14
|
+
AutoC is a collection of Ruby modules related to automatic C source code generation:
|
15
|
+
1) Multi-file C module generator.
|
16
|
+
2) Generators for strongly-typed generic collections similar to those from the C++ standard template library.
|
18
17
|
email: fougas@mail.ru
|
19
18
|
executables: []
|
20
19
|
extensions: []
|
21
20
|
extra_rdoc_files: []
|
22
21
|
files:
|
23
|
-
- lib/autoc/
|
24
|
-
- lib/autoc/
|
25
|
-
- lib/autoc/
|
22
|
+
- lib/autoc/code.rb
|
23
|
+
- lib/autoc/collection/hash_map.rb
|
24
|
+
- lib/autoc/collection/hash_set.rb
|
25
|
+
- lib/autoc/collection/list.rb
|
26
|
+
- lib/autoc/collection/queue.rb
|
27
|
+
- lib/autoc/collection/vector.rb
|
28
|
+
- lib/autoc/collection.rb
|
29
|
+
- lib/autoc/type.rb
|
26
30
|
- lib/autoc.rb
|
27
|
-
-
|
31
|
+
- doc/AutoC/Code.html
|
32
|
+
- doc/AutoC/Collection.html
|
33
|
+
- doc/AutoC/HashMap.html
|
34
|
+
- doc/AutoC/HashSet.html
|
35
|
+
- doc/AutoC/List.html
|
36
|
+
- doc/AutoC/Module/File.html
|
37
|
+
- doc/AutoC/Module/Header.html
|
38
|
+
- doc/AutoC/Module/Source.html
|
39
|
+
- doc/AutoC/Module.html
|
40
|
+
- doc/AutoC/Priority.html
|
41
|
+
- doc/AutoC/Queue.html
|
42
|
+
- doc/AutoC/Type.html
|
43
|
+
- doc/AutoC/UserDefinedType.html
|
44
|
+
- doc/AutoC/Vector.html
|
45
|
+
- doc/AutoC.html
|
46
|
+
- doc/class_list.html
|
47
|
+
- doc/css/common.css
|
48
|
+
- doc/css/full_list.css
|
49
|
+
- doc/css/style.css
|
50
|
+
- doc/file.README.html
|
51
|
+
- doc/file_list.html
|
52
|
+
- doc/frames.html
|
53
|
+
- doc/index.html
|
54
|
+
- doc/js/app.js
|
55
|
+
- doc/js/full_list.js
|
56
|
+
- doc/js/jquery.js
|
57
|
+
- doc/method_list.html
|
58
|
+
- doc/top-level-namespace.html
|
59
|
+
- doc/_index.html
|
28
60
|
- test/test.c
|
61
|
+
- test/test.h
|
29
62
|
- test/test.rb
|
30
63
|
- test/test_auto.c
|
31
64
|
- test/test_auto.h
|
@@ -33,26 +66,26 @@ files:
|
|
33
66
|
homepage: http://autoc.sourceforge.net/
|
34
67
|
licenses:
|
35
68
|
- BSD
|
69
|
+
metadata: {}
|
36
70
|
post_install_message:
|
37
71
|
rdoc_options: []
|
38
72
|
require_paths:
|
39
73
|
- lib
|
40
74
|
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
75
|
requirements:
|
43
|
-
- -
|
76
|
+
- - '>='
|
44
77
|
- !ruby/object:Gem::Version
|
45
78
|
version: '1.8'
|
46
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
-
none: false
|
48
80
|
requirements:
|
49
|
-
- -
|
81
|
+
- - '>='
|
50
82
|
- !ruby/object:Gem::Version
|
51
83
|
version: '0'
|
52
84
|
requirements: []
|
53
85
|
rubyforge_project:
|
54
|
-
rubygems_version:
|
86
|
+
rubygems_version: 2.0.14
|
55
87
|
signing_key:
|
56
|
-
specification_version:
|
88
|
+
specification_version: 4
|
57
89
|
summary: A host of Ruby modules related to automatic C source code generation
|
58
90
|
test_files: []
|
91
|
+
has_rdoc:
|
@@ -1,1794 +0,0 @@
|
|
1
|
-
require "set"
|
2
|
-
require "autoc/code_builder"
|
3
|
-
|
4
|
-
|
5
|
-
=begin rdoc
|
6
|
-
Generators for strongly-typed C data containers similar to C++ STL container classes.
|
7
|
-
|
8
|
-
The data types used as elements for generated containers may be of almost arbitrary type,
|
9
|
-
with either value or reference semantics. A data type may be supplied with a host of user-defined functions
|
10
|
-
performing specific operations such as cloning, destruction and a like on it.
|
11
|
-
If no such function is specified, a default operation is generated.
|
12
|
-
|
13
|
-
A data structure generator with name <code>type</code> creates a C struct named <code>type</code> and a host of functions named <code>type*()</code>.
|
14
|
-
From now on, the following convention is applied:
|
15
|
-
when referring to a generated C function the container name portion of a function is abbreviated by the hash sign <code>#</code>, for example, the full method
|
16
|
-
<code>BlackBoxPut()</code> of a data container <code>BlackBox</code> will be abbreviated as <code>#Put()</code>.
|
17
|
-
|
18
|
-
Some notes on generated data structures:
|
19
|
-
|
20
|
-
* Use proper pair of construction and destruction functions: those containers created on stack with <code>#Ctor()</code>
|
21
|
-
must be destroyed with <code>#Dtor()</code> while those created on heap with <code>#New()</code> must be destroyed with <code>#Destroy()</code>.
|
22
|
-
=end
|
23
|
-
module DataStructBuilder
|
24
|
-
|
25
|
-
|
26
|
-
# :nodoc:
|
27
|
-
PrologueCode = Class.new(CodeBuilder::Code) do
|
28
|
-
def write_intf(stream)
|
29
|
-
stream << %$
|
30
|
-
#include <stddef.h>
|
31
|
-
#include <stdlib.h>
|
32
|
-
#include <malloc.h>
|
33
|
-
#include <assert.h>
|
34
|
-
#ifndef __DATA_STRUCT_INLINE
|
35
|
-
#if defined(_MSC_VER) || defined(__PGI)
|
36
|
-
#define __DATA_STRUCT_INLINE __inline static
|
37
|
-
#elif __STDC_VERSION__ >= 199901L && !defined(__DMC__)
|
38
|
-
#define __DATA_STRUCT_INLINE inline static
|
39
|
-
#else
|
40
|
-
#define __DATA_STRUCT_INLINE static
|
41
|
-
#endif
|
42
|
-
#endif
|
43
|
-
#ifndef __DATA_STRUCT_EXTERN
|
44
|
-
#if defined(__cplusplus)
|
45
|
-
#define __DATA_STRUCT_EXTERN extern "C"
|
46
|
-
#else
|
47
|
-
#define __DATA_STRUCT_EXTERN extern
|
48
|
-
#endif
|
49
|
-
#endif
|
50
|
-
$
|
51
|
-
stream << %$
|
52
|
-
#include <stdio.h>
|
53
|
-
$ if $debug
|
54
|
-
end
|
55
|
-
end.new # PrologueCode
|
56
|
-
|
57
|
-
|
58
|
-
=begin rdoc
|
59
|
-
Base class for all C data container generators.
|
60
|
-
=end
|
61
|
-
class Code < CodeBuilder::Code
|
62
|
-
undef abort;
|
63
|
-
@@overrides = {:malloc=>"malloc", :calloc=>"calloc", :free=>"free", :assert=>"assert", :abort=>"abort", :extern=>"__DATA_STRUCT_EXTERN", :static=>"static", :inline=>"__DATA_STRUCT_INLINE"}
|
64
|
-
# String-like prefix for generated data type. Must be a valid C identifier.
|
65
|
-
attr_reader :type
|
66
|
-
# Setups the data structure generator.
|
67
|
-
# +type+ is a C type name used as a prefix for generated container functions. It must be a valid C identifier.
|
68
|
-
def initialize(type)
|
69
|
-
@type = type.to_s # TODO validate
|
70
|
-
end
|
71
|
-
protected
|
72
|
-
# :nodoc:
|
73
|
-
def method_missing(method, *args)
|
74
|
-
if @@overrides.include?(method)
|
75
|
-
@@overrides[method]
|
76
|
-
else
|
77
|
-
s = method.to_s.chomp('?')
|
78
|
-
@type + s[0].capitalize + s[1..-1]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end # Code
|
82
|
-
|
83
|
-
|
84
|
-
=begin rdoc
|
85
|
-
Indicates that the type class including this module provides the assignment operation.
|
86
|
-
The user-defined function is assigned to the key +:assign+ and
|
87
|
-
is expected to have the signature +type+ _assignment-function_(+type+).
|
88
|
-
The C function provided might return its argument or a new copy. It is also responsible for such things like ownership management etc.
|
89
|
-
When no user-defined function is specified, this module generates simple value assignment with = operator.
|
90
|
-
=end
|
91
|
-
module Assignable
|
92
|
-
Methods = [:assign] # :nodoc:
|
93
|
-
# Returns +true+ when used-defined assignment function is specified and +false+ otherwise.
|
94
|
-
def assign?
|
95
|
-
!descriptor[:assign].nil?
|
96
|
-
end
|
97
|
-
# Returns string representing the C assignment expression for +obj+.
|
98
|
-
# +obj+ is a string-like object containing the C expression to be injected.
|
99
|
-
def assign(obj)
|
100
|
-
assign? ? "#{descriptor[:assign]}(#{obj})" : "(#{obj})"
|
101
|
-
end
|
102
|
-
# :nodoc:
|
103
|
-
def write_intf_assign(stream)
|
104
|
-
stream << "#{type} #{descriptor[:assign]}(#{type});" if assign?
|
105
|
-
end
|
106
|
-
end # Assignable
|
107
|
-
|
108
|
-
|
109
|
-
=begin rdoc
|
110
|
-
Indicates that the type class including this module provides the equality testing operation.
|
111
|
-
The user-defined function is assigned to the key +:equal+
|
112
|
-
and is expected to have the signature int _equality-function_(+type+, +type+).
|
113
|
-
The C function provided must return non-zero value when the values are considered equal and zero value otherwise.
|
114
|
-
When no user-defined function is specified, this module generates simple value identity testing with == operator.
|
115
|
-
=end
|
116
|
-
module EqualityTestable
|
117
|
-
Methods = [:equal] # :nodoc:
|
118
|
-
# Returns +true+ when used-defined equality testing function is specified and +false+ otherwise.
|
119
|
-
def equal?
|
120
|
-
!descriptor[:equal].nil?
|
121
|
-
end
|
122
|
-
# Returns string representing the C expression comparison of +lt+ and +rt+.
|
123
|
-
# +lt+ and +rt+ are the string-like objects containing the C expression to be injected.
|
124
|
-
def equal(lt, rt)
|
125
|
-
equal? ? "#{descriptor[:equal]}(#{lt},#{rt})" : "(#{lt}==#{rt})"
|
126
|
-
end
|
127
|
-
# :nodoc:
|
128
|
-
def write_intf_equal(stream)
|
129
|
-
stream << "int #{descriptor[:equal]}(#{type},#{type});" if equal?
|
130
|
-
end
|
131
|
-
end # EqualityTestable
|
132
|
-
|
133
|
-
|
134
|
-
=begin rdoc
|
135
|
-
Indicates that the type class including this module provides the comparison operation.
|
136
|
-
The user-defined function is assigned to the key +:compare+
|
137
|
-
and is expected to have the signature int _compare-function_(+type+, +type+).
|
138
|
-
The C function provided must return value greater than zero when the first argument is considered greater than the second,
|
139
|
-
value less than zero when the first argument is considered smaller than the second and zero value when the two arguments are
|
140
|
-
considered equal.
|
141
|
-
When no user-defined function is specified, this module generates simple value comparison with < and > operators.
|
142
|
-
=end
|
143
|
-
module Comparable
|
144
|
-
Methods = [:compare] # :nodoc:
|
145
|
-
# Returns +true+ when wither used-defined or default equality testing function is specified and +false+ otherwise.
|
146
|
-
def compare?
|
147
|
-
descriptor.include?(:compare)
|
148
|
-
end
|
149
|
-
# Returns string representing the C expression comparison of +lt+ and +rt+.
|
150
|
-
# +lt+ and +rt+ are the string-like objects containing the C expression to be injected.
|
151
|
-
def compare(lt, rt)
|
152
|
-
compare = descriptor[:compare]
|
153
|
-
compare.nil? ? "(#{lt} > #{rt} ? +1 : (#{lt} < #{rt} ? -1 : 0))" : "#{compare}(#{lt},#{rt})"
|
154
|
-
end
|
155
|
-
# :nodoc:
|
156
|
-
def write_intf_compare(stream)
|
157
|
-
compare = descriptor[:compare]
|
158
|
-
stream << "int #{compare}(#{type},#{type});" unless compare.nil?
|
159
|
-
end
|
160
|
-
end # Comparable
|
161
|
-
|
162
|
-
|
163
|
-
=begin rdoc
|
164
|
-
Indicates that the type class including this module provides the hash code calculation.
|
165
|
-
The user-defined function is assigned to the key +:hash+
|
166
|
-
and is expected to have the signature +size_t+ _hash-function_(+type+).
|
167
|
-
The C function provided is expected to return a hash code of its argument.
|
168
|
-
When no user-defined function is specified, this module generates simple casting to the +size_t+ type.
|
169
|
-
=end
|
170
|
-
module Hashable
|
171
|
-
Methods = [:hash] # :nodoc:
|
172
|
-
# Returns +true+ when used-defined hashing function is specified and +false+ otherwise.
|
173
|
-
def hash?
|
174
|
-
!descriptor[:hash].nil?
|
175
|
-
end
|
176
|
-
# Returns string representing the C hashing expression for +obj+.
|
177
|
-
# +obj+ is a string-like object containing the C expression to be injected.
|
178
|
-
def hash(obj)
|
179
|
-
hash? ? "#{descriptor[:hash]}(#{obj})" : "((size_t)(#{obj}))" # TODO really size_t?
|
180
|
-
end
|
181
|
-
# :nodoc:
|
182
|
-
def write_intf_hash(stream)
|
183
|
-
stream << "size_t #{descriptor[:hash]}(#{type});" if hash?
|
184
|
-
end
|
185
|
-
end # Hashable
|
186
|
-
|
187
|
-
|
188
|
-
=begin rdoc
|
189
|
-
Indicates that the type class including this module provides the type construction with default value.
|
190
|
-
The user-defined function is assigned to the key +:ctor+
|
191
|
-
and is expected to have the signature +type+ _ctor-function_(+void+).
|
192
|
-
The C function provided is expected to return a new object initialized with default values.
|
193
|
-
When no user-defined function is specified, this module generates no code at all leaving the storage uninitialized.
|
194
|
-
=end
|
195
|
-
module Constructible
|
196
|
-
Methods = [:ctor] # :nodoc:
|
197
|
-
# Returns +true+ when used-defined construction function is specified and +false+ otherwise.
|
198
|
-
def ctor?
|
199
|
-
!descriptor[:ctor].nil?
|
200
|
-
end
|
201
|
-
# Returns string representing the C construction expression.
|
202
|
-
def ctor
|
203
|
-
ctor? ? "#{descriptor[:ctor]}()" : nil
|
204
|
-
end
|
205
|
-
# :nodoc:
|
206
|
-
def write_intf_ctor(stream)
|
207
|
-
stream << "#{type} #{descriptor[:ctor]}(void);" if ctor?
|
208
|
-
end
|
209
|
-
end # Constructible
|
210
|
-
|
211
|
-
|
212
|
-
=begin rdoc
|
213
|
-
Indicates that the type class including this module provides the type destruction.
|
214
|
-
The user-defined function is assigned to the key +:dtor+
|
215
|
-
and is expected to have the signature +void+ _dtor-function_(+type+).
|
216
|
-
The C function provided is expected to fully destroy the object (decrease reference count, reclaim the storage, whatever).
|
217
|
-
When no user-defined function is specified, this module generates no code at all.
|
218
|
-
The object destruction is performed prior the container destruction, on object removal/replacement.
|
219
|
-
=end
|
220
|
-
module Destructible
|
221
|
-
Methods = [:dtor] # :nodoc:
|
222
|
-
# Returns +true+ when used-defined construction function is specified and +false+ otherwise.
|
223
|
-
def dtor?
|
224
|
-
!descriptor[:dtor].nil?
|
225
|
-
end
|
226
|
-
# Returns string representing the C construction expression.
|
227
|
-
def dtor(obj)
|
228
|
-
dtor? ? "#{descriptor[:dtor]}(#{obj})" : nil
|
229
|
-
end
|
230
|
-
# :nodoc:
|
231
|
-
def write_intf_dtor(stream)
|
232
|
-
stream << "void #{descriptor[:dtor]}(#{type});" if dtor?
|
233
|
-
end
|
234
|
-
end # Destructible
|
235
|
-
|
236
|
-
|
237
|
-
=begin rdoc
|
238
|
-
Base class for user-defined data types intended to be put into the generated data containers.
|
239
|
-
A descendant of this class is assumed to include one or more the following capability modules to indicate that
|
240
|
-
the type supports specific operation: rdoc-ref:Assignable rdoc-ref:Equal rdoc-ref:Hashable rdoc-ref:Constructible rdoc-ref:Destructible
|
241
|
-
=end
|
242
|
-
class Type
|
243
|
-
##
|
244
|
-
# String representing C type. Must be a valid C type declaration.
|
245
|
-
attr_reader :type
|
246
|
-
##
|
247
|
-
# Constructs the user-defined data type.
|
248
|
-
# +descriptor+ is a +Hash+-like object describing the type to be created.
|
249
|
-
# The only mandatory key is +:type+ which is set to the C type declaration.
|
250
|
-
# The rest of specified keys is type-specific and is determined by included capability modules.
|
251
|
-
#
|
252
|
-
# === type description examples
|
253
|
-
#
|
254
|
-
# [1] A simple integer data type with value semantics and no user-defined functions attached: {:type=>'int'}.
|
255
|
-
#
|
256
|
-
# [2] A generic untyped pointer data type with value semantics: {:type=>'void*'}.
|
257
|
-
# A value of this type is not owned by container so no ownership management is performed.
|
258
|
-
#
|
259
|
-
# [3] A pointer to a structure with reference semantics and used-defined operations:
|
260
|
-
# {:type=>'struct Point*', :assign=>'PointPtrAssign', :dtor=>'PointPtrDtor'}.
|
261
|
-
# A value of this type will be owned by container.
|
262
|
-
def initialize(descriptor)
|
263
|
-
@descriptor = descriptor
|
264
|
-
@type = descriptor[:type]
|
265
|
-
end
|
266
|
-
# :nodoc:
|
267
|
-
def write_intf(stream)
|
268
|
-
methods = []
|
269
|
-
self.class.included_modules.each do |m|
|
270
|
-
begin
|
271
|
-
methods.concat(m::Methods)
|
272
|
-
rescue NameError
|
273
|
-
end
|
274
|
-
end
|
275
|
-
methods.each do |m|
|
276
|
-
send("write_intf_#{m}", stream)
|
277
|
-
end
|
278
|
-
end
|
279
|
-
# May be nil.
|
280
|
-
def code
|
281
|
-
descriptor.is_a?(CodeBuilder::Code) ? descriptor : (descriptor[:forward] ? ForwardCode.new(descriptor[:forward]) : nil)
|
282
|
-
end
|
283
|
-
protected
|
284
|
-
##
|
285
|
-
# Used by included modules to retrieve the type description supplied to constructor.
|
286
|
-
attr_reader :descriptor
|
287
|
-
end # Type
|
288
|
-
|
289
|
-
|
290
|
-
# :nodoc:
|
291
|
-
class ForwardCode < CodeBuilder::Code
|
292
|
-
attr_reader :forward
|
293
|
-
def priority
|
294
|
-
CodeBuilder::Priority::MAX
|
295
|
-
end
|
296
|
-
def initialize(forward)
|
297
|
-
@forward = forward
|
298
|
-
end
|
299
|
-
def write_intf(stream)
|
300
|
-
stream << forward
|
301
|
-
end
|
302
|
-
def hash
|
303
|
-
forward.hash
|
304
|
-
end
|
305
|
-
def ==(other)
|
306
|
-
equal?(other) || self.class == other.class && self.forward == other.forward
|
307
|
-
end
|
308
|
-
alias :eql? :==
|
309
|
-
end # ForwardCode
|
310
|
-
|
311
|
-
|
312
|
-
module Writers
|
313
|
-
Visibilities = Set.new [:public, :private, :static]
|
314
|
-
def initialize(type, visibility = :public)
|
315
|
-
super(type)
|
316
|
-
raise unless Visibilities.include?(visibility)
|
317
|
-
@visibility = visibility
|
318
|
-
end
|
319
|
-
# :nodoc:
|
320
|
-
def write_intf(stream)
|
321
|
-
case @visibility
|
322
|
-
when :public
|
323
|
-
write_exported_types(stream)
|
324
|
-
write_exported_declarations(stream, extern, inline)
|
325
|
-
end
|
326
|
-
end
|
327
|
-
# :nodoc:
|
328
|
-
def write_decls(stream)
|
329
|
-
case @visibility
|
330
|
-
when :private
|
331
|
-
write_exported_types(stream)
|
332
|
-
write_exported_declarations(stream, extern, inline)
|
333
|
-
when :static
|
334
|
-
write_exported_types(stream)
|
335
|
-
write_exported_declarations(stream, static, inline)
|
336
|
-
end
|
337
|
-
end
|
338
|
-
# :nodoc:
|
339
|
-
def write_defs(stream)
|
340
|
-
case @visibility
|
341
|
-
when :public, :private
|
342
|
-
write_implementations(stream, nil)
|
343
|
-
when :static
|
344
|
-
write_implementations(stream, static)
|
345
|
-
end
|
346
|
-
end
|
347
|
-
# def write_exported_types(stream)
|
348
|
-
# def write_exported_declarations(stream, declare, define)
|
349
|
-
# def write_implementations(stream, define)
|
350
|
-
end # Writers
|
351
|
-
|
352
|
-
|
353
|
-
##
|
354
|
-
# Internal base class for data structures which need one types specification, such as vectors, sets etc.
|
355
|
-
class Structure < Code
|
356
|
-
include Writers
|
357
|
-
attr_reader :element
|
358
|
-
# :nodoc:
|
359
|
-
def initialize(type, element_descriptor, visibility = :public)
|
360
|
-
super(type, visibility)
|
361
|
-
@element = new_element_type(element_descriptor)
|
362
|
-
@self_hash = {:type=>"#{type}*", :assign=>assign, :ctor=>new, :dtor=>destroy}
|
363
|
-
end
|
364
|
-
# :nodoc:
|
365
|
-
def [](symbol)
|
366
|
-
@self_hash[symbol]
|
367
|
-
end
|
368
|
-
# :nodoc:
|
369
|
-
def entities; [PrologueCode, @element.code].compact end
|
370
|
-
# :nodoc:
|
371
|
-
def write_intf(stream)
|
372
|
-
element.write_intf(stream)
|
373
|
-
super
|
374
|
-
end
|
375
|
-
# def new_element_type()
|
376
|
-
end # Struct
|
377
|
-
|
378
|
-
|
379
|
-
=begin rdoc
|
380
|
-
Data structure representing simple light-weight vector with capabilities similar to C array, with optional bounds checking.
|
381
|
-
=end
|
382
|
-
class Vector < Structure
|
383
|
-
def initialize(*args)
|
384
|
-
super
|
385
|
-
@self_hash.delete(:ctor) # unlike other data structures, Vector has no parameterless constructor
|
386
|
-
end
|
387
|
-
# :nodoc:
|
388
|
-
def write_exported_types(stream)
|
389
|
-
stream << %$
|
390
|
-
typedef struct #{type} #{type};
|
391
|
-
typedef struct #{it} #{it};
|
392
|
-
struct #{type} {
|
393
|
-
#{element.type}* values;
|
394
|
-
size_t element_count;
|
395
|
-
size_t ref_count;
|
396
|
-
};
|
397
|
-
struct #{it} {
|
398
|
-
#{type}* vector;
|
399
|
-
size_t index;
|
400
|
-
};
|
401
|
-
$
|
402
|
-
end
|
403
|
-
def write_exported_declarations(stream, declare, define)
|
404
|
-
stream << %$
|
405
|
-
#{declare} void #{ctor}(#{type}*, size_t);
|
406
|
-
#{declare} void #{dtor}(#{type}*);
|
407
|
-
#{declare} #{type}* #{new}(size_t);
|
408
|
-
#{declare} void #{destroy}(#{type}*);
|
409
|
-
#{declare} #{type}* #{assign}(#{type}*);
|
410
|
-
#{declare} void #{resize}(#{type}*, size_t);
|
411
|
-
#{declare} int #{within}(#{type}*, size_t);
|
412
|
-
#{declare} void #{itCtor}(#{it}*, #{type}*);
|
413
|
-
#{declare} int #{itHasNext}(#{it}*);
|
414
|
-
#{declare} #{element.type} #{itNext}(#{it}*);
|
415
|
-
#{define} #{element.type}* #{ref}(#{type}* self, size_t index) {
|
416
|
-
#{assert}(self);
|
417
|
-
#{assert}(#{within}(self, index));
|
418
|
-
return &self->values[index];
|
419
|
-
}
|
420
|
-
#{define} #{element.type} #{get}(#{type}* self, size_t index) {
|
421
|
-
#{assert}(self);
|
422
|
-
#{assert}(#{within}(self, index));
|
423
|
-
return *#{ref}(self, index);
|
424
|
-
}
|
425
|
-
#{define} void #{set}(#{type}* self, size_t index, #{element.type} value) {
|
426
|
-
#{element.type}* ref;
|
427
|
-
#{assert}(self);
|
428
|
-
#{assert}(#{within}(self, index));
|
429
|
-
ref = #{ref}(self, index);
|
430
|
-
#{element.dtor("*ref")};
|
431
|
-
*ref = #{element.assign(:value)};
|
432
|
-
}
|
433
|
-
#{define} size_t #{size}(#{type}* self) {
|
434
|
-
#{assert}(self);
|
435
|
-
return self->element_count;
|
436
|
-
}
|
437
|
-
$
|
438
|
-
stream << %$#{declare} void #{sort}(#{type}*);$ if element.compare?
|
439
|
-
end
|
440
|
-
# :nodoc:
|
441
|
-
def write_implementations(stream, define)
|
442
|
-
stream << %$
|
443
|
-
#{define} void #{ctor}(#{type}* self, size_t element_count) {
|
444
|
-
#{assert}(self);
|
445
|
-
#{assert}(element_count > 0);
|
446
|
-
self->element_count = element_count;
|
447
|
-
self->values = (#{element.type}*)#{calloc}(element_count, sizeof(#{element.type})); #{assert}(self->values);
|
448
|
-
#{construct_stmt("self->values", 0, "self->element_count-1")};
|
449
|
-
}
|
450
|
-
#{define} void #{dtor}(#{type}* self) {
|
451
|
-
#{assert}(self);
|
452
|
-
#{destruct_stmt("self->values", 0, "self->element_count-1")};
|
453
|
-
#{free}(self->values);
|
454
|
-
}
|
455
|
-
#{define} #{type}* #{new}(size_t element_count) {
|
456
|
-
#{type}* self = (#{type}*)#{malloc}(sizeof(#{type})); #{assert}(self);
|
457
|
-
#{ctor}(self, element_count);
|
458
|
-
self->ref_count = 0;
|
459
|
-
return self;
|
460
|
-
}
|
461
|
-
#{define} void #{destroy}(#{type}* self) {
|
462
|
-
#{assert}(self);
|
463
|
-
if(!--self->ref_count) {
|
464
|
-
#{dtor}(self);
|
465
|
-
#{free}(self);
|
466
|
-
}
|
467
|
-
}
|
468
|
-
#{define} #{type}* #{assign}(#{type}* self) {
|
469
|
-
++self->ref_count;
|
470
|
-
return self;
|
471
|
-
}
|
472
|
-
#{define} void #{resize}(#{type}* self, size_t element_count) {
|
473
|
-
#{assert}(self);
|
474
|
-
if(self->element_count != element_count) {
|
475
|
-
size_t count;
|
476
|
-
#{element.type}* values = (#{element.type}*)#{calloc}(element_count, sizeof(#{element.type})); #{assert}(values);
|
477
|
-
if(self->element_count > element_count) {
|
478
|
-
#{destruct_stmt("self->values", "element_count", "self->element_count-1")};
|
479
|
-
count = element_count;
|
480
|
-
} else {
|
481
|
-
#{construct_stmt("values", "self->element_count", "element_count-1")};
|
482
|
-
count = self->element_count;
|
483
|
-
}
|
484
|
-
{
|
485
|
-
size_t index;
|
486
|
-
for(index = 0; index < count; ++index) {
|
487
|
-
values[index] = self->values[index];
|
488
|
-
}
|
489
|
-
}
|
490
|
-
#{free}(self->values);
|
491
|
-
self->element_count = element_count;
|
492
|
-
self->values = values;
|
493
|
-
}
|
494
|
-
}
|
495
|
-
#{define} int #{within}(#{type}* self, size_t index) {
|
496
|
-
#{assert}(self);
|
497
|
-
return index < self->element_count;
|
498
|
-
}
|
499
|
-
#{define} void #{itCtor}(#{it}* self, #{type}* vector) {
|
500
|
-
#{assert}(self);
|
501
|
-
#{assert}(vector);
|
502
|
-
self->vector = vector;
|
503
|
-
self->index = 0;
|
504
|
-
}
|
505
|
-
#{define} int #{itHasNext}(#{it}* self) {
|
506
|
-
#{assert}(self);
|
507
|
-
return self->index < #{size}(self->vector);
|
508
|
-
}
|
509
|
-
#{define} #{element.type} #{itNext}(#{it}* self) {
|
510
|
-
#{assert}(self);
|
511
|
-
return #{get}(self->vector, self->index++);
|
512
|
-
}
|
513
|
-
$
|
514
|
-
stream << %$
|
515
|
-
static int #{comparator}(const void* lp, const void* rp) {
|
516
|
-
return #{element.compare("*(#{element.type}*)lp", "*(#{element.type}*)rp")};
|
517
|
-
}
|
518
|
-
#{define} void #{sort}(#{type}* self) {
|
519
|
-
#{assert}(self);
|
520
|
-
qsort(self->values, self->element_count, sizeof(#{element.type}), #{comparator});
|
521
|
-
}
|
522
|
-
$ if element.compare?
|
523
|
-
end
|
524
|
-
protected
|
525
|
-
# :nodoc:
|
526
|
-
class ElementType < DataStructBuilder::Type
|
527
|
-
include Assignable, Constructible, Destructible, Comparable
|
528
|
-
end # ElementType
|
529
|
-
# :nodoc:
|
530
|
-
def new_element_type(type)
|
531
|
-
ElementType.new(type)
|
532
|
-
end
|
533
|
-
private
|
534
|
-
# :nodoc:
|
535
|
-
def construct_stmt(values, from, to)
|
536
|
-
if element.ctor?
|
537
|
-
%${
|
538
|
-
size_t index;
|
539
|
-
for(index = #{from}; index <= #{to}; ++index) #{values}[index] = #{element.assign(element.ctor())};
|
540
|
-
}$
|
541
|
-
end
|
542
|
-
end
|
543
|
-
# :nodoc:
|
544
|
-
def destruct_stmt(values, from, to)
|
545
|
-
if element.dtor?
|
546
|
-
%${
|
547
|
-
size_t index;
|
548
|
-
for(index = #{from}; index <= #{to}; ++index) #{element.dtor(values+"[index]")};
|
549
|
-
}$
|
550
|
-
end
|
551
|
-
end
|
552
|
-
end # Vector
|
553
|
-
|
554
|
-
|
555
|
-
=begin rdoc
|
556
|
-
Data structure representing singly-linked list.
|
557
|
-
=end
|
558
|
-
class List < Structure
|
559
|
-
# :nodoc:
|
560
|
-
def write_exported_types(stream)
|
561
|
-
stream << %$
|
562
|
-
typedef struct #{node} #{node};
|
563
|
-
typedef struct #{type} #{type};
|
564
|
-
typedef struct #{it} #{it};
|
565
|
-
struct #{type} {
|
566
|
-
#{node}* head_node;
|
567
|
-
size_t node_count;
|
568
|
-
size_t ref_count;
|
569
|
-
};
|
570
|
-
struct #{it} {
|
571
|
-
#{node}* next_node;
|
572
|
-
};
|
573
|
-
struct #{node} {
|
574
|
-
#{element.type} element;
|
575
|
-
#{node}* next_node;
|
576
|
-
};
|
577
|
-
$
|
578
|
-
end
|
579
|
-
# :nodoc:
|
580
|
-
def write_exported_declarations(stream, declare, define)
|
581
|
-
stream << %$
|
582
|
-
#{declare} void #{ctor}(#{type}*);
|
583
|
-
#{declare} void #{dtor}(#{type}*);
|
584
|
-
#{declare} void #{purge}(#{type}*);
|
585
|
-
#{declare} #{type}* #{new}(void);
|
586
|
-
#{declare} void #{destroy}(#{type}*);
|
587
|
-
#{declare} #{type}* #{assign}(#{type}*);
|
588
|
-
#{declare} #{element.type} #{get}(#{type}*);
|
589
|
-
#{declare} void #{add}(#{type}*, #{element.type});
|
590
|
-
#{declare} void #{chop}(#{type}*);
|
591
|
-
#{declare} int #{contains}(#{type}*, #{element.type});
|
592
|
-
#{declare} #{element.type} #{find}(#{type}*, #{element.type});
|
593
|
-
#{declare} int #{replace}(#{type}*, #{element.type}, #{element.type});
|
594
|
-
#{declare} int #{replaceAll}(#{type}*, #{element.type}, #{element.type});
|
595
|
-
#{declare} int #{remove}(#{type}*, #{element.type});
|
596
|
-
#{declare} int #{removeAll}(#{type}*, #{element.type});
|
597
|
-
#{declare} size_t #{size}(#{type}*);
|
598
|
-
#{declare} int #{empty}(#{type}*);
|
599
|
-
#{declare} void #{itCtor}(#{it}*, #{type}*);
|
600
|
-
#{declare} int #{itHasNext}(#{it}*);
|
601
|
-
#{declare} #{element.type} #{itNext}(#{it}*);
|
602
|
-
$
|
603
|
-
end
|
604
|
-
# :nodoc:
|
605
|
-
def write_implementations(stream, define)
|
606
|
-
stream << %$
|
607
|
-
#{define} void #{ctor}(#{type}* self) {
|
608
|
-
#{assert}(self);
|
609
|
-
self->head_node = NULL;
|
610
|
-
self->node_count = 0;
|
611
|
-
}
|
612
|
-
#{define} void #{dtor}(#{type}* self) {
|
613
|
-
#{node}* node;
|
614
|
-
#{assert}(self);
|
615
|
-
#{destruct_stmt};
|
616
|
-
node = self->head_node;
|
617
|
-
while(node) {
|
618
|
-
#{node}* this_node = node;
|
619
|
-
node = node->next_node;
|
620
|
-
#{free}(this_node);
|
621
|
-
}
|
622
|
-
}
|
623
|
-
#{define} #{type}* #{new}(void) {
|
624
|
-
#{type}* self = (#{type}*)#{malloc}(sizeof(#{type})); #{assert}(self);
|
625
|
-
#{ctor}(self);
|
626
|
-
self->ref_count = 0;
|
627
|
-
return self;
|
628
|
-
}
|
629
|
-
#{define} void #{destroy}(#{type}* self) {
|
630
|
-
#{assert}(self);
|
631
|
-
if(!--self->ref_count) {
|
632
|
-
#{dtor}(self);
|
633
|
-
#{free}(self);
|
634
|
-
}
|
635
|
-
}
|
636
|
-
#{define} #{type}* #{assign}(#{type}* self) {
|
637
|
-
++self->ref_count;
|
638
|
-
return self;
|
639
|
-
}
|
640
|
-
#{define} void #{purge}(#{type}* self) {
|
641
|
-
#{dtor}(self);
|
642
|
-
#{ctor}(self);
|
643
|
-
}
|
644
|
-
#{define} #{element.type} #{get}(#{type}* self) {
|
645
|
-
#{assert}(self);
|
646
|
-
#{assert}(!#{empty}(self));
|
647
|
-
return self->head_node->element;
|
648
|
-
}
|
649
|
-
#{define} void #{chop}(#{type}* self) {
|
650
|
-
#{node}* node;
|
651
|
-
#{assert}(self);
|
652
|
-
#{assert}(!#{empty}(self));
|
653
|
-
node = self->head_node;
|
654
|
-
#{element.dtor("node->element")};
|
655
|
-
self->head_node = self->head_node->next_node;
|
656
|
-
--self->node_count;
|
657
|
-
#{free}(node);
|
658
|
-
}
|
659
|
-
#{define} void #{add}(#{type}* self, #{element.type} element) {
|
660
|
-
#{node}* node;
|
661
|
-
#{assert}(self);
|
662
|
-
node = (#{node}*)#{malloc}(sizeof(#{node})); #{assert}(node);
|
663
|
-
node->element = #{element.assign("element")};
|
664
|
-
node->next_node = self->head_node;
|
665
|
-
self->head_node = node;
|
666
|
-
++self->node_count;
|
667
|
-
}
|
668
|
-
#{define} int #{contains}(#{type}* self, #{element.type} what) {
|
669
|
-
#{node}* node;
|
670
|
-
#{assert}(self);
|
671
|
-
what = #{element.assign("what")};
|
672
|
-
node = self->head_node;
|
673
|
-
while(node) {
|
674
|
-
if(#{element.equal("node->element", "what")}) {
|
675
|
-
#{element.dtor("what")};
|
676
|
-
return 1;
|
677
|
-
}
|
678
|
-
node = node->next_node;
|
679
|
-
}
|
680
|
-
#{element.dtor("what")};
|
681
|
-
return 0;
|
682
|
-
}
|
683
|
-
#{define} #{element.type} #{find}(#{type}* self, #{element.type} what) {
|
684
|
-
#{node}* node;
|
685
|
-
#{assert}(self);
|
686
|
-
what = #{element.assign("what")};
|
687
|
-
#{assert}(#{contains}(self, what));
|
688
|
-
node = self->head_node;
|
689
|
-
while(node) {
|
690
|
-
if(#{element.equal("node->element", "what")}) {
|
691
|
-
#{element.dtor("what")};
|
692
|
-
return node->element;
|
693
|
-
}
|
694
|
-
node = node->next_node;
|
695
|
-
}
|
696
|
-
#{abort}();
|
697
|
-
}
|
698
|
-
#{define} int #{replace}(#{type}* self, #{element.type} what, #{element.type} with) {
|
699
|
-
#{node}* node;
|
700
|
-
#{assert}(self);
|
701
|
-
what = #{element.assign("what")};
|
702
|
-
with = #{element.assign("with")};
|
703
|
-
node = self->head_node;
|
704
|
-
while(node) {
|
705
|
-
if(#{element.equal("node->element", "what")}) {
|
706
|
-
#{element.dtor("node->element")};
|
707
|
-
node->element = #{element.assign("with")};
|
708
|
-
#{element.dtor("what")};
|
709
|
-
#{element.dtor("with")};
|
710
|
-
return 1;
|
711
|
-
}
|
712
|
-
node = node->next_node;
|
713
|
-
}
|
714
|
-
#{element.dtor("what")};
|
715
|
-
#{element.dtor("with")};
|
716
|
-
return 0;
|
717
|
-
}
|
718
|
-
#{define} int #{replaceAll}(#{type}* self, #{element.type} what, #{element.type} with) {
|
719
|
-
#{node}* node;
|
720
|
-
int count = 0;
|
721
|
-
#{assert}(self);
|
722
|
-
what = #{element.assign("what")};
|
723
|
-
with = #{element.assign("with")};
|
724
|
-
node = self->head_node;
|
725
|
-
while(node) {
|
726
|
-
if(#{element.equal("node->element", "what")}) {
|
727
|
-
#{element.dtor("node->element")};
|
728
|
-
node->element = #{element.assign("with")};
|
729
|
-
++count;
|
730
|
-
}
|
731
|
-
node = node->next_node;
|
732
|
-
}
|
733
|
-
#{element.dtor("what")};
|
734
|
-
#{element.dtor("with")};
|
735
|
-
return count;
|
736
|
-
}
|
737
|
-
#{define} int #{remove}(#{type}* self, #{element.type} what) {
|
738
|
-
#{node}* node;
|
739
|
-
#{node}* prev_node;
|
740
|
-
int found = 0;
|
741
|
-
#{assert}(self);
|
742
|
-
what = #{element.assign("what")};
|
743
|
-
node = self->head_node;
|
744
|
-
prev_node = NULL;
|
745
|
-
while(node) {
|
746
|
-
if(#{element.equal("node->element", "what")}) {
|
747
|
-
#{element.dtor("node->element")};
|
748
|
-
if(prev_node) {
|
749
|
-
prev_node->next_node = node->next_node ? node->next_node : NULL;
|
750
|
-
} else {
|
751
|
-
self->head_node = node->next_node ? node->next_node : NULL;
|
752
|
-
}
|
753
|
-
--self->node_count;
|
754
|
-
#{free}(node);
|
755
|
-
found = 1;
|
756
|
-
break;
|
757
|
-
}
|
758
|
-
prev_node = node;
|
759
|
-
node = node->next_node;
|
760
|
-
}
|
761
|
-
#{element.dtor("what")};
|
762
|
-
return found;
|
763
|
-
}
|
764
|
-
#{define} int #{removeAll}(#{type}* self, #{element.type} what) {
|
765
|
-
#{node}* node;
|
766
|
-
#{node}* prev_node;
|
767
|
-
int count = 0;
|
768
|
-
#{assert}(self);
|
769
|
-
what = #{element.assign("what")};
|
770
|
-
node = self->head_node;
|
771
|
-
prev_node = NULL;
|
772
|
-
while(node) {
|
773
|
-
if(#{element.equal("node->element", "what")}) {
|
774
|
-
#{element.dtor("node->element")};
|
775
|
-
if(prev_node) {
|
776
|
-
prev_node->next_node = node->next_node ? node->next_node : NULL;
|
777
|
-
} else {
|
778
|
-
self->head_node = node->next_node ? node->next_node : NULL;
|
779
|
-
}
|
780
|
-
--self->node_count;
|
781
|
-
#{free}(node);
|
782
|
-
++count;
|
783
|
-
}
|
784
|
-
prev_node = node;
|
785
|
-
node = node->next_node;
|
786
|
-
}
|
787
|
-
#{element.dtor("what")};
|
788
|
-
return count;
|
789
|
-
}
|
790
|
-
#{define} size_t #{size}(#{type}* self) {
|
791
|
-
#{assert}(self);
|
792
|
-
return self->node_count;
|
793
|
-
}
|
794
|
-
#{define} int #{empty}(#{type}* self) {
|
795
|
-
#{assert}(self);
|
796
|
-
return !self->node_count;
|
797
|
-
}
|
798
|
-
#{define} void #{itCtor}(#{it}* self, #{type}* list) {
|
799
|
-
#{assert}(self);
|
800
|
-
#{assert}(list);
|
801
|
-
self->next_node = list->head_node;
|
802
|
-
}
|
803
|
-
#{define} int #{itHasNext}(#{it}* self) {
|
804
|
-
#{assert}(self);
|
805
|
-
return self->next_node != NULL;
|
806
|
-
}
|
807
|
-
#{define} #{element.type} #{itNext}(#{it}* self) {
|
808
|
-
#{node}* node;
|
809
|
-
#{assert}(self);
|
810
|
-
node = self->next_node;
|
811
|
-
self->next_node = self->next_node->next_node;
|
812
|
-
return node->element;
|
813
|
-
}
|
814
|
-
$
|
815
|
-
end
|
816
|
-
protected
|
817
|
-
# :nodoc:
|
818
|
-
class ElementType < DataStructBuilder::Type
|
819
|
-
include Assignable, Destructible, EqualityTestable
|
820
|
-
end # ElementType
|
821
|
-
# :nodoc:
|
822
|
-
def new_element_type(hash)
|
823
|
-
ElementType.new(hash)
|
824
|
-
end
|
825
|
-
private
|
826
|
-
# :nodoc:
|
827
|
-
def destruct_stmt
|
828
|
-
if element.dtor?
|
829
|
-
%${
|
830
|
-
#{it} it;
|
831
|
-
#{itCtor}(&it, self);
|
832
|
-
while(#{itHasNext}(&it)) {
|
833
|
-
#{element.type} e = #{itNext}(&it);
|
834
|
-
#{element.dtor(:e)};
|
835
|
-
}
|
836
|
-
}$
|
837
|
-
end
|
838
|
-
end
|
839
|
-
end # List
|
840
|
-
|
841
|
-
|
842
|
-
=begin rdoc
|
843
|
-
Data structure representing doubly-linked list.
|
844
|
-
=end
|
845
|
-
class Queue < Structure
|
846
|
-
# :nodoc:
|
847
|
-
def write_exported_types(stream)
|
848
|
-
stream << %$
|
849
|
-
typedef struct #{node} #{node};
|
850
|
-
typedef struct #{type} #{type};
|
851
|
-
typedef struct #{it} #{it};
|
852
|
-
struct #{type} {
|
853
|
-
#{node}* head_node;
|
854
|
-
#{node}* tail_node;
|
855
|
-
size_t node_count;
|
856
|
-
size_t ref_count;
|
857
|
-
};
|
858
|
-
struct #{it} {
|
859
|
-
#{node}* next_node;
|
860
|
-
int forward;
|
861
|
-
};
|
862
|
-
struct #{node} {
|
863
|
-
#{element.type} element;
|
864
|
-
#{node}* prev_node;
|
865
|
-
#{node}* next_node;
|
866
|
-
};
|
867
|
-
$
|
868
|
-
end
|
869
|
-
# :nodoc:
|
870
|
-
def write_exported_declarations(stream, declare, define)
|
871
|
-
stream << %$
|
872
|
-
#{declare} void #{ctor}(#{type}*);
|
873
|
-
#{declare} void #{dtor}(#{type}*);
|
874
|
-
#{declare} void #{purge}(#{type}*);
|
875
|
-
#{declare} #{type}* #{new}(void);
|
876
|
-
#{declare} void #{destroy}(#{type}*);
|
877
|
-
#{declare} #{type}* #{assign}(#{type}*);
|
878
|
-
#{declare} #{element.type} #{head}(#{type}*);
|
879
|
-
#{declare} #{element.type} #{tail}(#{type}*);
|
880
|
-
#{declare} void #{append}(#{type}*, #{element.type});
|
881
|
-
#{declare} void #{prepend}(#{type}*, #{element.type});
|
882
|
-
#{declare} void #{chopHead}(#{type}*);
|
883
|
-
#{declare} void #{chopTail}(#{type}*);
|
884
|
-
#{declare} int #{contains}(#{type}*, #{element.type});
|
885
|
-
#{declare} #{element.type} #{find}(#{type}*, #{element.type});
|
886
|
-
#{declare} int #{replace}(#{type}*, #{element.type}, #{element.type});
|
887
|
-
#{declare} int #{replaceAll}(#{type}*, #{element.type}, #{element.type});
|
888
|
-
#{declare} int #{remove}(#{type}*, #{element.type});
|
889
|
-
#{declare} int #{removeAll}(#{type}*, #{element.type});
|
890
|
-
#{declare} size_t #{size}(#{type}*);
|
891
|
-
#{declare} int #{empty}(#{type}*);
|
892
|
-
#{declare} void #{itCtor}(#{it}*, #{type}*, int);
|
893
|
-
#{declare} int #{itHasNext}(#{it}*);
|
894
|
-
#{declare} #{element.type} #{itNext}(#{it}*);
|
895
|
-
$
|
896
|
-
end
|
897
|
-
# :nodoc:
|
898
|
-
def write_implementations(stream, define)
|
899
|
-
stream << %$
|
900
|
-
#{define} void #{ctor}(#{type}* self) {
|
901
|
-
#{assert}(self);
|
902
|
-
self->head_node = self->tail_node = NULL;
|
903
|
-
self->node_count = 0;
|
904
|
-
}
|
905
|
-
#{define} void #{dtor}(#{type}* self) {
|
906
|
-
#{node}* node;
|
907
|
-
#{assert}(self);
|
908
|
-
#{destruct_stmt};
|
909
|
-
node = self->head_node;
|
910
|
-
while(node) {
|
911
|
-
#{node}* this_node = node;
|
912
|
-
node = node->next_node;
|
913
|
-
#{free}(this_node);
|
914
|
-
}
|
915
|
-
}
|
916
|
-
#{define} #{type}* #{new}(void) {
|
917
|
-
#{type}* self = (#{type}*)#{malloc}(sizeof(#{type})); #{assert}(self);
|
918
|
-
#{ctor}(self);
|
919
|
-
self->ref_count = 0;
|
920
|
-
return self;
|
921
|
-
}
|
922
|
-
#{define} void #{destroy}(#{type}* self) {
|
923
|
-
#{assert}(self);
|
924
|
-
if(!--self->ref_count) {
|
925
|
-
#{dtor}(self);
|
926
|
-
#{free}(self);
|
927
|
-
}
|
928
|
-
}
|
929
|
-
#{define} #{type}* #{assign}(#{type}* self) {
|
930
|
-
++self->ref_count;
|
931
|
-
return self;
|
932
|
-
}
|
933
|
-
#{define} void #{purge}(#{type}* self) {
|
934
|
-
#{dtor}(self);
|
935
|
-
#{ctor}(self);
|
936
|
-
}
|
937
|
-
#{define} #{element.type} #{head}(#{type}* self) {
|
938
|
-
#{assert}(self);
|
939
|
-
#{assert}(!#{empty}(self));
|
940
|
-
return self->head_node->element;
|
941
|
-
}
|
942
|
-
#{define} #{element.type} #{tail}(#{type}* self) {
|
943
|
-
#{assert}(self);
|
944
|
-
#{assert}(!#{empty}(self));
|
945
|
-
return self->tail_node->element;
|
946
|
-
}
|
947
|
-
#{define} void #{chopHead}(#{type}* self) {
|
948
|
-
#{node}* node;
|
949
|
-
#{assert}(self);
|
950
|
-
#{assert}(!#{empty}(self));
|
951
|
-
node = self->head_node;
|
952
|
-
#{element.dtor("node->element")};
|
953
|
-
self->head_node = self->head_node->next_node;
|
954
|
-
self->head_node->prev_node = NULL;
|
955
|
-
--self->node_count;
|
956
|
-
#{free}(node);
|
957
|
-
}
|
958
|
-
#{define} void #{chopTail}(#{type}* self) {
|
959
|
-
#{node}* node;
|
960
|
-
#{assert}(self);
|
961
|
-
#{assert}(!#{empty}(self));
|
962
|
-
node = self->tail_node;
|
963
|
-
#{element.dtor("node->element")};
|
964
|
-
self->tail_node = self->tail_node->prev_node;
|
965
|
-
self->tail_node->next_node = NULL;
|
966
|
-
--self->node_count;
|
967
|
-
#{free}(node);
|
968
|
-
}
|
969
|
-
#{define} void #{append}(#{type}* self, #{element.type} element) {
|
970
|
-
#{node}* node;
|
971
|
-
#{assert}(self);
|
972
|
-
node = (#{node}*)#{malloc}(sizeof(#{node})); #{assert}(node);
|
973
|
-
node->element = #{element.assign("element")};
|
974
|
-
if(#{empty}(self)) {
|
975
|
-
node->prev_node = node->next_node = NULL;
|
976
|
-
self->tail_node = self->head_node = node;
|
977
|
-
} else {
|
978
|
-
node->next_node = NULL;
|
979
|
-
node->prev_node = self->tail_node;
|
980
|
-
self->tail_node->next_node = node;
|
981
|
-
self->tail_node = node;
|
982
|
-
}
|
983
|
-
++self->node_count;
|
984
|
-
}
|
985
|
-
#{define} void #{prepend}(#{type}* self, #{element.type} element) {
|
986
|
-
#{node}* node;
|
987
|
-
#{assert}(self);
|
988
|
-
node = (#{node}*)#{malloc}(sizeof(#{node})); #{assert}(node);
|
989
|
-
node->element = #{element.assign("element")};
|
990
|
-
if(#{empty}(self)) {
|
991
|
-
node->prev_node = node->next_node = NULL;
|
992
|
-
self->tail_node = self->head_node = node;
|
993
|
-
} else {
|
994
|
-
node->prev_node = NULL;
|
995
|
-
node->next_node = self->head_node;
|
996
|
-
self->head_node->prev_node = node;
|
997
|
-
self->head_node = node;
|
998
|
-
}
|
999
|
-
++self->node_count;
|
1000
|
-
}
|
1001
|
-
#{define} int #{contains}(#{type}* self, #{element.type} what) {
|
1002
|
-
#{node}* node;
|
1003
|
-
#{assert}(self);
|
1004
|
-
what = #{element.assign("what")};
|
1005
|
-
node = self->head_node;
|
1006
|
-
while(node) {
|
1007
|
-
if(#{element.equal("node->element", "what")}) {
|
1008
|
-
#{element.dtor("what")};
|
1009
|
-
return 1;
|
1010
|
-
}
|
1011
|
-
node = node->next_node;
|
1012
|
-
}
|
1013
|
-
#{element.dtor("what")};
|
1014
|
-
return 0;
|
1015
|
-
}
|
1016
|
-
#{define} #{element.type} #{find}(#{type}* self, #{element.type} what) {
|
1017
|
-
#{node}* node;
|
1018
|
-
#{assert}(self);
|
1019
|
-
what = #{element.assign("what")};
|
1020
|
-
#{assert}(#{contains}(self, what));
|
1021
|
-
node = self->head_node;
|
1022
|
-
while(node) {
|
1023
|
-
if(#{element.equal("node->element", "what")}) {
|
1024
|
-
#{element.dtor("what")};
|
1025
|
-
return node->element;
|
1026
|
-
}
|
1027
|
-
node = node->next_node;
|
1028
|
-
}
|
1029
|
-
#{abort}();
|
1030
|
-
}
|
1031
|
-
#{define} int #{replace}(#{type}* self, #{element.type} what, #{element.type} with) {
|
1032
|
-
#{node}* node;
|
1033
|
-
#{assert}(self);
|
1034
|
-
what = #{element.assign("what")};
|
1035
|
-
with = #{element.assign("with")};
|
1036
|
-
node = self->head_node;
|
1037
|
-
while(node) {
|
1038
|
-
if(#{element.equal("node->element", "what")}) {
|
1039
|
-
#{element.dtor("node->element")};
|
1040
|
-
node->element = #{element.assign("with")};
|
1041
|
-
#{element.dtor("what")};
|
1042
|
-
#{element.dtor("with")};
|
1043
|
-
return 1;
|
1044
|
-
}
|
1045
|
-
node = node->next_node;
|
1046
|
-
}
|
1047
|
-
#{element.dtor("what")};
|
1048
|
-
#{element.dtor("with")};
|
1049
|
-
return 0;
|
1050
|
-
}
|
1051
|
-
#{define} int #{replaceAll}(#{type}* self, #{element.type} what, #{element.type} with) {
|
1052
|
-
#{node}* node;
|
1053
|
-
int count = 0;
|
1054
|
-
#{assert}(self);
|
1055
|
-
what = #{element.assign("what")};
|
1056
|
-
with = #{element.assign("with")};
|
1057
|
-
node = self->head_node;
|
1058
|
-
while(node) {
|
1059
|
-
if(#{element.equal("node->element", "what")}) {
|
1060
|
-
#{element.dtor("node->element")};
|
1061
|
-
node->element = #{element.assign("with")};
|
1062
|
-
++count;
|
1063
|
-
}
|
1064
|
-
node = node->next_node;
|
1065
|
-
}
|
1066
|
-
#{element.dtor("what")};
|
1067
|
-
#{element.dtor("with")};
|
1068
|
-
return count;
|
1069
|
-
}
|
1070
|
-
#{define} int #{remove}(#{type}* self, #{element.type} what) {
|
1071
|
-
#{node}* node;
|
1072
|
-
int found = 0;
|
1073
|
-
#{assert}(self);
|
1074
|
-
what = #{element.assign("what")};
|
1075
|
-
node = self->head_node;
|
1076
|
-
while(node) {
|
1077
|
-
if(#{element.equal("node->element", "what")}) {
|
1078
|
-
#{node} *prev = node->prev_node, *next = node->next_node;
|
1079
|
-
#{element.dtor("node->element")};
|
1080
|
-
if(prev && next) {
|
1081
|
-
prev->next_node = next;
|
1082
|
-
next->prev_node = prev;
|
1083
|
-
} else if(prev) {
|
1084
|
-
prev->next_node = NULL;
|
1085
|
-
self->tail_node = prev;
|
1086
|
-
} else {
|
1087
|
-
next->prev_node = NULL;
|
1088
|
-
self->head_node = next;
|
1089
|
-
}
|
1090
|
-
--self->node_count;
|
1091
|
-
#{free}(node);
|
1092
|
-
found = 1;
|
1093
|
-
break;
|
1094
|
-
}
|
1095
|
-
node = node->next_node;
|
1096
|
-
}
|
1097
|
-
#{element.dtor("what")};
|
1098
|
-
return found;
|
1099
|
-
}
|
1100
|
-
#{define} int #{removeAll}(#{type}* self, #{element.type} what) {
|
1101
|
-
#{node}* node;
|
1102
|
-
int count = 0;
|
1103
|
-
#{assert}(self);
|
1104
|
-
what = #{element.assign("what")};
|
1105
|
-
node = self->head_node;
|
1106
|
-
while(node) {
|
1107
|
-
if(#{element.equal("node->element", "what")}) {
|
1108
|
-
#{node} *prev = node->prev_node, *next = node->next_node;
|
1109
|
-
#{element.dtor("node->element")};
|
1110
|
-
if(prev && next) {
|
1111
|
-
prev->next_node = next;
|
1112
|
-
next->prev_node = prev;
|
1113
|
-
} else if(prev) {
|
1114
|
-
prev->next_node = NULL;
|
1115
|
-
self->tail_node = prev;
|
1116
|
-
} else {
|
1117
|
-
next->prev_node = NULL;
|
1118
|
-
self->head_node = next;
|
1119
|
-
}
|
1120
|
-
--self->node_count;
|
1121
|
-
#{free}(node);
|
1122
|
-
++count;
|
1123
|
-
}
|
1124
|
-
node = node->next_node;
|
1125
|
-
}
|
1126
|
-
#{element.dtor("what")};
|
1127
|
-
return count;
|
1128
|
-
}
|
1129
|
-
#{define} size_t #{size}(#{type}* self) {
|
1130
|
-
#{assert}(self);
|
1131
|
-
return self->node_count;
|
1132
|
-
}
|
1133
|
-
#{define} int #{empty}(#{type}* self) {
|
1134
|
-
#{assert}(self);
|
1135
|
-
return !self->node_count;
|
1136
|
-
}
|
1137
|
-
#{define} void #{itCtor}(#{it}* self, #{type}* list, int forward) {
|
1138
|
-
#{assert}(self);
|
1139
|
-
#{assert}(list);
|
1140
|
-
self->forward = forward;
|
1141
|
-
self->next_node = forward ? list->head_node : list->tail_node;
|
1142
|
-
}
|
1143
|
-
#{define} int #{itHasNext}(#{it}* self) {
|
1144
|
-
#{assert}(self);
|
1145
|
-
return self->next_node != NULL;
|
1146
|
-
}
|
1147
|
-
#{define} #{element.type} #{itNext}(#{it}* self) {
|
1148
|
-
#{node}* node;
|
1149
|
-
#{assert}(self);
|
1150
|
-
node = self->next_node;
|
1151
|
-
self->next_node = self->forward ? self->next_node->next_node : self->next_node->prev_node;
|
1152
|
-
return node->element;
|
1153
|
-
}
|
1154
|
-
$
|
1155
|
-
end
|
1156
|
-
protected
|
1157
|
-
# :nodoc:
|
1158
|
-
class ElementType < DataStructBuilder::Type
|
1159
|
-
include Assignable, Destructible, EqualityTestable
|
1160
|
-
end # ElementType
|
1161
|
-
# :nodoc:
|
1162
|
-
def new_element_type(hash)
|
1163
|
-
ElementType.new(hash)
|
1164
|
-
end
|
1165
|
-
private
|
1166
|
-
# :nodoc:
|
1167
|
-
def destruct_stmt
|
1168
|
-
if element.dtor?
|
1169
|
-
%${
|
1170
|
-
#{it} it;
|
1171
|
-
#{itCtor}(&it, self);
|
1172
|
-
while(#{itHasNext}(&it)) {
|
1173
|
-
#{element.type} e = #{itNext}(&it);
|
1174
|
-
#{element.dtor(:e)};
|
1175
|
-
}
|
1176
|
-
}$
|
1177
|
-
end
|
1178
|
-
end
|
1179
|
-
end # Queue
|
1180
|
-
|
1181
|
-
|
1182
|
-
=begin rdoc
|
1183
|
-
Data structure representing hashed set.
|
1184
|
-
=end
|
1185
|
-
class HashSet < Structure
|
1186
|
-
# :nodoc:
|
1187
|
-
def initialize(*args)
|
1188
|
-
super
|
1189
|
-
@list = new_list
|
1190
|
-
end
|
1191
|
-
# :nodoc:
|
1192
|
-
def write_exported_types(stream)
|
1193
|
-
@list.write_exported_types(stream)
|
1194
|
-
stream << %$
|
1195
|
-
typedef struct #{type} #{type};
|
1196
|
-
typedef struct #{it} #{it};
|
1197
|
-
struct #{type} {
|
1198
|
-
#{@list.type}* buckets;
|
1199
|
-
size_t bucket_count, min_bucket_count;
|
1200
|
-
size_t size, min_size, max_size;
|
1201
|
-
unsigned min_fill, max_fill, capacity_multiplier; /* ?*1e-2 */
|
1202
|
-
size_t ref_count;
|
1203
|
-
};
|
1204
|
-
struct #{it} {
|
1205
|
-
#{type}* set;
|
1206
|
-
int bucket_index;
|
1207
|
-
#{@list.it} it;
|
1208
|
-
};
|
1209
|
-
$
|
1210
|
-
end
|
1211
|
-
def write_exported_declarations(stream, declare, define)
|
1212
|
-
stream << %$
|
1213
|
-
#{declare} void #{ctor}(#{type}*);
|
1214
|
-
#{declare} void #{dtor}(#{type}*);
|
1215
|
-
#{declare} #{type}* #{new}(void);
|
1216
|
-
#{declare} void #{destroy}(#{type}*);
|
1217
|
-
#{declare} #{type}* #{assign}(#{type}*);
|
1218
|
-
#{declare} void #{purge}(#{type}*);
|
1219
|
-
#{declare} void #{rehash}(#{type}*);
|
1220
|
-
#{declare} int #{contains}(#{type}*, #{element.type});
|
1221
|
-
#{declare} #{element.type} #{get}(#{type}*, #{element.type});
|
1222
|
-
#{declare} size_t #{size}(#{type}*);
|
1223
|
-
#{declare} int #{empty}(#{type}*);
|
1224
|
-
#{declare} int #{put}(#{type}*, #{element.type});
|
1225
|
-
#{declare} void #{replace}(#{type}*, #{element.type});
|
1226
|
-
#{declare} int #{remove}(#{type}*, #{element.type});
|
1227
|
-
#{declare} void #{not?}(#{type}*, #{type}*);
|
1228
|
-
#{declare} void #{and?}(#{type}*, #{type}*);
|
1229
|
-
#{declare} void #{or?}(#{type}*, #{type}*);
|
1230
|
-
#{declare} void #{xor?}(#{type}*, #{type}*);
|
1231
|
-
#{declare} void #{itCtor}(#{it}*, #{type}*);
|
1232
|
-
#{declare} int #{itHasNext}(#{it}*);
|
1233
|
-
#{declare} #{element.type} #{itNext}(#{it}*);
|
1234
|
-
$
|
1235
|
-
stream << %$#{declare} void #{dumpStats}(#{type}*, FILE*);$ if $debug
|
1236
|
-
end
|
1237
|
-
# :nodoc:
|
1238
|
-
def write_implementations(stream, define)
|
1239
|
-
@list.write_exported_declarations(stream, static, inline)
|
1240
|
-
@list.write_implementations(stream, static)
|
1241
|
-
stream << %$
|
1242
|
-
#{define} void #{ctor}(#{type}* self) {
|
1243
|
-
#{assert}(self);
|
1244
|
-
self->min_bucket_count = 16;
|
1245
|
-
self->min_fill = 20;
|
1246
|
-
self->max_fill = 80;
|
1247
|
-
self->min_size = (size_t)((float)self->min_fill/100*self->min_bucket_count);
|
1248
|
-
self->max_size = (size_t)((float)self->max_fill/100*self->min_bucket_count);
|
1249
|
-
self->capacity_multiplier = 200;
|
1250
|
-
self->buckets = NULL;
|
1251
|
-
#{rehash}(self);
|
1252
|
-
}
|
1253
|
-
#{define} void #{dtor}(#{type}* self) {
|
1254
|
-
size_t i;
|
1255
|
-
#{assert}(self);
|
1256
|
-
for(i = 0; i < self->bucket_count; ++i) {
|
1257
|
-
#{@list.dtor}(&self->buckets[i]);
|
1258
|
-
}
|
1259
|
-
#{free}(self->buckets);
|
1260
|
-
}
|
1261
|
-
#{define} #{type}* #{new}(void) {
|
1262
|
-
#{type}* self = (#{type}*)#{malloc}(sizeof(#{type})); #{assert}(self);
|
1263
|
-
#{ctor}(self);
|
1264
|
-
self->ref_count = 0;
|
1265
|
-
return self;
|
1266
|
-
}
|
1267
|
-
#{define} void #{destroy}(#{type}* self) {
|
1268
|
-
#{assert}(self);
|
1269
|
-
if(!--self->ref_count) {
|
1270
|
-
#{dtor}(self);
|
1271
|
-
#{free}(self);
|
1272
|
-
}
|
1273
|
-
}
|
1274
|
-
#{define} #{type}* #{assign}(#{type}* self) {
|
1275
|
-
++self->ref_count;
|
1276
|
-
return self;
|
1277
|
-
}
|
1278
|
-
#{define} void #{purge}(#{type}* self) {
|
1279
|
-
#{assert}(self);
|
1280
|
-
#{dtor}(self);
|
1281
|
-
self->buckets = NULL;
|
1282
|
-
#{rehash}(self);
|
1283
|
-
}
|
1284
|
-
#{define} void #{rehash}(#{type}* self) {
|
1285
|
-
#{@list.type}* buckets;
|
1286
|
-
size_t i, bucket_count, size, fill;
|
1287
|
-
#{assert}(self);
|
1288
|
-
#{assert}(self->min_fill > 0);
|
1289
|
-
#{assert}(self->max_fill > 0);
|
1290
|
-
#{assert}(self->min_fill < self->max_fill);
|
1291
|
-
#{assert}(self->min_bucket_count > 0);
|
1292
|
-
if(self->buckets) {
|
1293
|
-
if(self->min_size < self->size && self->size < self->max_size) return;
|
1294
|
-
fill = (size_t)((float)self->size/self->bucket_count*100);
|
1295
|
-
if(fill > self->max_fill) {
|
1296
|
-
bucket_count = (size_t)((float)self->bucket_count/100*self->capacity_multiplier);
|
1297
|
-
} else
|
1298
|
-
if(fill < self->min_fill && self->bucket_count > self->min_bucket_count) {
|
1299
|
-
bucket_count = (size_t)((float)self->bucket_count/self->capacity_multiplier*100);
|
1300
|
-
if(bucket_count < self->min_bucket_count) bucket_count = self->min_bucket_count;
|
1301
|
-
} else
|
1302
|
-
return;
|
1303
|
-
size = self->size;
|
1304
|
-
self->min_size = (size_t)((float)self->min_fill/100*size);
|
1305
|
-
self->max_size = (size_t)((float)self->max_fill/100*size);
|
1306
|
-
} else {
|
1307
|
-
bucket_count = self->min_bucket_count;
|
1308
|
-
size = 0;
|
1309
|
-
}
|
1310
|
-
buckets = (#{@list.type}*)#{malloc}(bucket_count*sizeof(#{@list.type})); #{assert}(buckets);
|
1311
|
-
for(i = 0; i < bucket_count; ++i) {
|
1312
|
-
#{@list.ctor}(&buckets[i]);
|
1313
|
-
}
|
1314
|
-
if(self->buckets) {
|
1315
|
-
#{it} it;
|
1316
|
-
#{itCtor}(&it, self);
|
1317
|
-
while(#{itHasNext}(&it)) {
|
1318
|
-
#{@list.type}* bucket;
|
1319
|
-
#{element.type} element = #{itNext}(&it);
|
1320
|
-
bucket = &buckets[#{element.hash("element")} % bucket_count];
|
1321
|
-
#{@list.add}(bucket, element);
|
1322
|
-
}
|
1323
|
-
#{dtor}(self);
|
1324
|
-
}
|
1325
|
-
self->buckets = buckets;
|
1326
|
-
self->bucket_count = bucket_count;
|
1327
|
-
self->size = size;
|
1328
|
-
}
|
1329
|
-
#{define} int #{contains}(#{type}* self, #{element.type} element) {
|
1330
|
-
int result;
|
1331
|
-
#{assert}(self);
|
1332
|
-
element = #{element.assign("element")};
|
1333
|
-
result = #{@list.contains}(&self->buckets[#{element.hash("element")} % self->bucket_count], element);
|
1334
|
-
#{element.dtor("element")};
|
1335
|
-
return result;
|
1336
|
-
}
|
1337
|
-
#{define} #{element.type} #{get}(#{type}* self, #{element.type} element) {
|
1338
|
-
#{element.type} result;
|
1339
|
-
#{assert}(self);
|
1340
|
-
element = #{element.assign("element")};
|
1341
|
-
#{assert}(#{contains}(self, element));
|
1342
|
-
result = #{@list.find}(&self->buckets[#{element.hash("element")} % self->bucket_count], element);
|
1343
|
-
#{element.dtor("element")};
|
1344
|
-
return result;
|
1345
|
-
}
|
1346
|
-
#{define} size_t #{size}(#{type}* self) {
|
1347
|
-
#{assert}(self);
|
1348
|
-
return self->size;
|
1349
|
-
}
|
1350
|
-
#{define} int #{empty}(#{type}* self) {
|
1351
|
-
#{assert}(self);
|
1352
|
-
return !self->size;
|
1353
|
-
}
|
1354
|
-
#{define} int #{put}(#{type}* self, #{element.type} element) {
|
1355
|
-
int contained = 1;
|
1356
|
-
#{@list.type}* bucket;
|
1357
|
-
#{assert}(self);
|
1358
|
-
element = #{element.assign("element")};
|
1359
|
-
bucket = &self->buckets[#{element.hash("element")} % self->bucket_count];
|
1360
|
-
if(!#{@list.contains}(bucket, element)) {
|
1361
|
-
#{@list.add}(bucket, element);
|
1362
|
-
++self->size;
|
1363
|
-
contained = 0;
|
1364
|
-
#{rehash}(self);
|
1365
|
-
}
|
1366
|
-
#{element.dtor("element")};
|
1367
|
-
return contained;
|
1368
|
-
}
|
1369
|
-
#{define} void #{replace}(#{type}* self, #{element.type} element) {
|
1370
|
-
#{@list.type}* bucket;
|
1371
|
-
#{assert}(self);
|
1372
|
-
element = #{element.assign("element")};
|
1373
|
-
bucket = &self->buckets[#{element.hash("element")} % self->bucket_count];
|
1374
|
-
if(!#{@list.replace}(bucket, element, element)) {
|
1375
|
-
#{@list.add}(bucket, element);
|
1376
|
-
++self->size;
|
1377
|
-
#{rehash}(self);
|
1378
|
-
}
|
1379
|
-
#{element.dtor("element")};
|
1380
|
-
}
|
1381
|
-
#{define} int #{remove}(#{type}* self, #{element.type} what) {
|
1382
|
-
int removed = 0;
|
1383
|
-
#{@list.type}* bucket;
|
1384
|
-
#{assert}(self);
|
1385
|
-
what = #{element.assign("what")};
|
1386
|
-
bucket = &self->buckets[#{element.hash("what")} % self->bucket_count];
|
1387
|
-
if(#{@list.remove}(bucket, what)) {
|
1388
|
-
--self->size;
|
1389
|
-
removed = 1;
|
1390
|
-
#{rehash}(self);
|
1391
|
-
}
|
1392
|
-
#{element.dtor("what")};
|
1393
|
-
return removed;
|
1394
|
-
}
|
1395
|
-
#{define} void #{not?}(#{type}* self, #{type}* other) {
|
1396
|
-
#{it} it;
|
1397
|
-
#{assert}(self);
|
1398
|
-
#{assert}(other);
|
1399
|
-
#{itCtor}(&it, other);
|
1400
|
-
while(#{itHasNext}(&it)) {
|
1401
|
-
#{remove}(self, #{itNext}(&it));
|
1402
|
-
}
|
1403
|
-
#{rehash}(self);
|
1404
|
-
}
|
1405
|
-
#{define} void #{or?}(#{type}* self, #{type}* other) {
|
1406
|
-
#{it} it;
|
1407
|
-
#{assert}(self);
|
1408
|
-
#{assert}(other);
|
1409
|
-
#{itCtor}(&it, other);
|
1410
|
-
while(#{itHasNext}(&it)) {
|
1411
|
-
#{put}(self, #{itNext}(&it));
|
1412
|
-
}
|
1413
|
-
#{rehash}(self);
|
1414
|
-
}
|
1415
|
-
#{define} void #{and?}(#{type}* self, #{type}* other) {
|
1416
|
-
#{it} it;
|
1417
|
-
#{type} set;
|
1418
|
-
#{assert}(self);
|
1419
|
-
#{assert}(other);
|
1420
|
-
#{ctor}(&set);
|
1421
|
-
#{itCtor}(&it, self);
|
1422
|
-
while(#{itHasNext}(&it)) {
|
1423
|
-
#{element.type} element = #{itNext}(&it);
|
1424
|
-
if(#{contains}(other, element)) #{put}(&set, element);
|
1425
|
-
}
|
1426
|
-
#{itCtor}(&it, other);
|
1427
|
-
while(#{itHasNext}(&it)) {
|
1428
|
-
#{element.type} element = #{itNext}(&it);
|
1429
|
-
if(#{contains}(self, element)) #{put}(&set, element);
|
1430
|
-
}
|
1431
|
-
#{dtor}(self);
|
1432
|
-
self->buckets = set.buckets;
|
1433
|
-
self->size = set.size;
|
1434
|
-
#{rehash}(self);
|
1435
|
-
/*#{dtor}(&set);*/
|
1436
|
-
}
|
1437
|
-
#{define} void #{xor?}(#{type}* self, #{type}* other) {
|
1438
|
-
#{it} it;
|
1439
|
-
#{type} set;
|
1440
|
-
#{assert}(self);
|
1441
|
-
#{assert}(other);
|
1442
|
-
#{ctor}(&set);
|
1443
|
-
#{itCtor}(&it, self);
|
1444
|
-
while(#{itHasNext}(&it)) {
|
1445
|
-
#{element.type} element = #{itNext}(&it);
|
1446
|
-
if(!#{contains}(other, element)) #{put}(&set, element);
|
1447
|
-
}
|
1448
|
-
#{itCtor}(&it, other);
|
1449
|
-
while(#{itHasNext}(&it)) {
|
1450
|
-
#{element.type} element = #{itNext}(&it);
|
1451
|
-
if(!#{contains}(self, element)) #{put}(&set, element);
|
1452
|
-
}
|
1453
|
-
#{dtor}(self);
|
1454
|
-
self->buckets = set.buckets;
|
1455
|
-
self->size = set.size;
|
1456
|
-
#{rehash}(self);
|
1457
|
-
/*#{dtor}(&set);*/
|
1458
|
-
}
|
1459
|
-
#{define} void #{itCtor}(#{it}* self, #{type}* set) {
|
1460
|
-
#{assert}(self);
|
1461
|
-
self->set = set;
|
1462
|
-
self->bucket_index = 0;
|
1463
|
-
#{@list.itCtor}(&self->it, &set->buckets[0]);
|
1464
|
-
}
|
1465
|
-
#{define} int #{itHasNext}(#{it}* self) {
|
1466
|
-
#{assert}(self);
|
1467
|
-
if(#{@list.itHasNext}(&self->it)) {
|
1468
|
-
return 1;
|
1469
|
-
} else {
|
1470
|
-
size_t i; for(i = self->bucket_index+1; i < self->set->bucket_count; ++i) {
|
1471
|
-
if(!#{@list.empty}(&self->set->buckets[i])) {
|
1472
|
-
return 1;
|
1473
|
-
}
|
1474
|
-
}
|
1475
|
-
return 0;
|
1476
|
-
}
|
1477
|
-
}
|
1478
|
-
#{define} #{element.type} #{itNext}(#{it}* self) {
|
1479
|
-
#{assert}(self);
|
1480
|
-
#{assert}(#{itHasNext}(self));
|
1481
|
-
if(#{@list.itHasNext}(&self->it)) {
|
1482
|
-
return #{@list.itNext}(&self->it);
|
1483
|
-
} else {
|
1484
|
-
size_t i; for(i = self->bucket_index+1; i < self->set->bucket_count; ++i) {
|
1485
|
-
if(!#{@list.empty}(&self->set->buckets[i])) {
|
1486
|
-
#{@list.itCtor}(&self->it, &self->set->buckets[i]);
|
1487
|
-
self->bucket_index = i;
|
1488
|
-
return #{@list.itNext}(&self->it);
|
1489
|
-
}
|
1490
|
-
}
|
1491
|
-
#{abort}();
|
1492
|
-
}
|
1493
|
-
}
|
1494
|
-
$
|
1495
|
-
stream << %$
|
1496
|
-
#{define} void #{dumpStats}(#{type}* self, FILE* file) {
|
1497
|
-
size_t index, min_size, max_size;
|
1498
|
-
#{assert}(self);
|
1499
|
-
#{assert}(file);
|
1500
|
-
min_size = self->size;
|
1501
|
-
max_size = 0;
|
1502
|
-
fprintf(file, "element count = %d\\n", self->size);
|
1503
|
-
fprintf(file, "bucket count = %d\\n", self->bucket_count);
|
1504
|
-
for(index = 0; index < self->bucket_count; ++index) {
|
1505
|
-
size_t bucket_size = #{@list.size}(&self->buckets[index]);
|
1506
|
-
if(min_size > bucket_size) min_size = bucket_size;
|
1507
|
-
if(max_size < bucket_size) max_size = bucket_size;
|
1508
|
-
fprintf(file, "[%d] element count = %d (%.1f%%)\\n", index, bucket_size, (double)bucket_size*100/self->size);
|
1509
|
-
}
|
1510
|
-
fprintf(file, "element count = [%d ... %d]\\n", min_size, max_size);
|
1511
|
-
}
|
1512
|
-
$ if $debug
|
1513
|
-
end
|
1514
|
-
protected
|
1515
|
-
# :nodoc:
|
1516
|
-
class ElementType < DataStructBuilder::Type
|
1517
|
-
include Assignable, Destructible, Hashable, EqualityTestable
|
1518
|
-
end # ElementType
|
1519
|
-
# :nodoc:
|
1520
|
-
def new_element_type(hash)
|
1521
|
-
@element_hash = hash
|
1522
|
-
ElementType.new(hash)
|
1523
|
-
end
|
1524
|
-
# :nodoc:
|
1525
|
-
def new_list
|
1526
|
-
List.new("#{type}List", @element_hash)
|
1527
|
-
end
|
1528
|
-
end # Set
|
1529
|
-
|
1530
|
-
|
1531
|
-
=begin rdoc
|
1532
|
-
Data structure representing hashed map.
|
1533
|
-
=end
|
1534
|
-
class HashMap < Code
|
1535
|
-
include Writers
|
1536
|
-
attr_reader :key, :value
|
1537
|
-
# :nodoc:
|
1538
|
-
def entities; [PrologueCode, @key.code, @value.code, @entry.code].compact end
|
1539
|
-
# :nodoc:
|
1540
|
-
def initialize(type, key_descriptor, value_descriptor, visibility = :public)
|
1541
|
-
super(type, visibility)
|
1542
|
-
@entry_hash = {:type=>entry, :hash=>entryHash, :equal=>entryEqual, :assign=>entryAssign, :dtor=>entryDtor}
|
1543
|
-
@entry = new_entry_type
|
1544
|
-
@entry_set = new_entry_set
|
1545
|
-
@key = new_key_type(key_descriptor)
|
1546
|
-
@value = new_value_type(value_descriptor)
|
1547
|
-
@self_hash = {:type=>"#{type}*", :assign=>assign, :ctor=>new, :dtor=>destroy}
|
1548
|
-
end
|
1549
|
-
# :nodoc:
|
1550
|
-
def [](symbol)
|
1551
|
-
@self_hash[symbol]
|
1552
|
-
end
|
1553
|
-
# :nodoc:
|
1554
|
-
def write_intf(stream)
|
1555
|
-
key.write_intf(stream)
|
1556
|
-
value.write_intf(stream)
|
1557
|
-
super
|
1558
|
-
end
|
1559
|
-
# :nodoc:
|
1560
|
-
def write_exported_types(stream)
|
1561
|
-
stream << %$
|
1562
|
-
typedef struct #{@entry.type} #{@entry.type};
|
1563
|
-
struct #{@entry.type} {
|
1564
|
-
#{key.type} key;
|
1565
|
-
#{value.type} value;
|
1566
|
-
int valid_value;
|
1567
|
-
};
|
1568
|
-
$
|
1569
|
-
@entry_set.write_exported_types(stream)
|
1570
|
-
stream << %$
|
1571
|
-
typedef struct #{type} #{type};
|
1572
|
-
typedef struct #{it} #{it};
|
1573
|
-
struct #{type} {
|
1574
|
-
#{@entry_set.type} entries;
|
1575
|
-
size_t ref_count;
|
1576
|
-
};
|
1577
|
-
struct #{it} {
|
1578
|
-
#{@entry_set.it} it;
|
1579
|
-
};
|
1580
|
-
$
|
1581
|
-
end
|
1582
|
-
# :nodoc:
|
1583
|
-
def write_exported_declarations(stream, declare, define)
|
1584
|
-
stream << %$
|
1585
|
-
#{declare} void #{ctor}(#{type}*);
|
1586
|
-
#{declare} void #{dtor}(#{type}*);
|
1587
|
-
#{declare} #{type}* #{new}(void);
|
1588
|
-
#{declare} void #{destroy}(#{type}*);
|
1589
|
-
#{declare} #{type}* #{assign}(#{type}*);
|
1590
|
-
#{declare} void #{purge}(#{type}*);
|
1591
|
-
#{declare} void #{rehash}(#{type}*);
|
1592
|
-
#{declare} size_t #{size}(#{type}*);
|
1593
|
-
#{declare} int #{empty}(#{type}*);
|
1594
|
-
#{declare} int #{containsKey}(#{type}*, #{key.type});
|
1595
|
-
#{declare} #{value.type} #{get}(#{type}*, #{key.type});
|
1596
|
-
#{declare} int #{put}(#{type}*, #{key.type}, #{value.type});
|
1597
|
-
#{declare} void #{replace}(#{type}*, #{key.type}, #{value.type});
|
1598
|
-
#{declare} int #{remove}(#{type}*, #{key.type});
|
1599
|
-
#{declare} void #{itCtor}(#{it}*, #{type}*);
|
1600
|
-
#{declare} int #{itHasNext}(#{it}*);
|
1601
|
-
#{declare} #{key.type} #{itNextKey}(#{it}*);
|
1602
|
-
#{declare} #{value.type} #{itNextValue}(#{it}*);
|
1603
|
-
#{declare} #{@entry.type} #{itNext}(#{it}*);
|
1604
|
-
$
|
1605
|
-
stream << %$#{declare} void #{dumpStats}(#{type}*, FILE*);$ if $debug
|
1606
|
-
|
1607
|
-
end
|
1608
|
-
# :nodoc:
|
1609
|
-
def write_implementations(stream, define)
|
1610
|
-
stream << %$
|
1611
|
-
static #{@entry.type} #{entryKeyOnly}(#{key.type} key) {
|
1612
|
-
#{@entry.type} entry;
|
1613
|
-
entry.key = key;
|
1614
|
-
entry.valid_value = 0;
|
1615
|
-
return entry;
|
1616
|
-
}
|
1617
|
-
static #{@entry.type} #{entryKeyValue}(#{key.type} key, #{value.type} value) {
|
1618
|
-
#{@entry.type} entry;
|
1619
|
-
entry.key = key;
|
1620
|
-
entry.value = value;
|
1621
|
-
entry.valid_value = 1;
|
1622
|
-
return entry;
|
1623
|
-
}
|
1624
|
-
static size_t #{entryHash}(#{@entry.type} entry) {
|
1625
|
-
return #{key.hash("entry.key")};
|
1626
|
-
}
|
1627
|
-
static int #{entryEqual}(#{@entry.type} lt, #{@entry.type} rt) {
|
1628
|
-
return #{key.equal("lt.key", "rt.key")};
|
1629
|
-
}
|
1630
|
-
static #{@entry.type} #{entryAssign}(#{@entry.type} entry) {
|
1631
|
-
entry.key = #{key.assign("entry.key")};
|
1632
|
-
if(entry.valid_value) entry.value = #{value.assign("entry.value")};
|
1633
|
-
return entry;
|
1634
|
-
}
|
1635
|
-
static void #{entryDtor}(#{@entry.type} entry) {
|
1636
|
-
#{key.dtor("entry.key")};
|
1637
|
-
if(entry.valid_value) #{value.dtor("entry.value")};
|
1638
|
-
}
|
1639
|
-
$
|
1640
|
-
@entry_set.write_exported_declarations(stream, static, inline)
|
1641
|
-
@entry_set.write_implementations(stream, static)
|
1642
|
-
stream << %$
|
1643
|
-
#{define} void #{ctor}(#{type}* self) {
|
1644
|
-
#{assert}(self);
|
1645
|
-
#{@entry_set.ctor}(&self->entries);
|
1646
|
-
}
|
1647
|
-
#{define} void #{dtor}(#{type}* self) {
|
1648
|
-
#{assert}(self);
|
1649
|
-
#{@entry_set.dtor}(&self->entries);
|
1650
|
-
}
|
1651
|
-
#{define} #{type}* #{new}(void) {
|
1652
|
-
#{type}* self = (#{type}*)#{malloc}(sizeof(#{type})); #{assert}(self);
|
1653
|
-
#{ctor}(self);
|
1654
|
-
self->ref_count = 0;
|
1655
|
-
return self;
|
1656
|
-
}
|
1657
|
-
#{define} void #{destroy}(#{type}* self) {
|
1658
|
-
#{assert}(self);
|
1659
|
-
if(!--self->ref_count) {
|
1660
|
-
#{dtor}(self);
|
1661
|
-
#{free}(self);
|
1662
|
-
}
|
1663
|
-
}
|
1664
|
-
#{define} void #{rehash}(#{type}* self) {
|
1665
|
-
#{assert}(self);
|
1666
|
-
#{@entry_set.rehash}(&self->entries);
|
1667
|
-
}
|
1668
|
-
#{define} #{type}* #{assign}(#{type}* self) {
|
1669
|
-
#{assert}(self);
|
1670
|
-
++self->ref_count;
|
1671
|
-
return self;
|
1672
|
-
}
|
1673
|
-
#{define} void #{purge}(#{type}* self) {
|
1674
|
-
#{assert}(self);
|
1675
|
-
#{@entry_set.purge}(&self->entries);
|
1676
|
-
}
|
1677
|
-
#{define} size_t #{size}(#{type}* self) {
|
1678
|
-
#{assert}(self);
|
1679
|
-
return #{@entry_set.size}(&self->entries);
|
1680
|
-
}
|
1681
|
-
#{define} int #{empty}(#{type}* self) {
|
1682
|
-
#{assert}(self);
|
1683
|
-
return #{@entry_set.empty}(&self->entries);
|
1684
|
-
}
|
1685
|
-
#{define} int #{containsKey}(#{type}* self, #{key.type} key) {
|
1686
|
-
int result;
|
1687
|
-
#{@entry.type} entry;
|
1688
|
-
#{assert}(self);
|
1689
|
-
entry = #{@entry.assign("#{entryKeyOnly}(key)")};
|
1690
|
-
result = #{@entry_set.contains}(&self->entries, entry);
|
1691
|
-
#{@entry.dtor("entry")};
|
1692
|
-
return result;
|
1693
|
-
}
|
1694
|
-
#{define} #{value.type} #{get}(#{type}* self, #{key.type} key) {
|
1695
|
-
#{value.type} result;
|
1696
|
-
#{@entry.type} entry;
|
1697
|
-
#{assert}(self);
|
1698
|
-
entry = #{@entry.assign("#{entryKeyOnly}(key)")};
|
1699
|
-
#{assert}(#{containsKey}(self, key));
|
1700
|
-
result = #{@entry_set.get}(&self->entries, entry).value;
|
1701
|
-
#{@entry.dtor("entry")};
|
1702
|
-
return result;
|
1703
|
-
}
|
1704
|
-
#{define} int #{put}(#{type}* self, #{key.type} key, #{value.type} value) {
|
1705
|
-
#{@entry.type} entry = #{@entry.assign("#{entryKeyValue}(key,value)")};
|
1706
|
-
#{assert}(self);
|
1707
|
-
if(!#{containsKey}(self, key)) {
|
1708
|
-
#{@entry_set.put}(&self->entries, entry);
|
1709
|
-
#{@entry.dtor("entry")};
|
1710
|
-
return 1;
|
1711
|
-
} else {
|
1712
|
-
#{@entry.dtor("entry")};
|
1713
|
-
return 0;
|
1714
|
-
}
|
1715
|
-
}
|
1716
|
-
#{define} void #{replace}(#{type}* self, #{key.type} key, #{value.type} value) {
|
1717
|
-
#{@entry.type} entry;
|
1718
|
-
#{assert}(self);
|
1719
|
-
entry = #{@entry.assign("#{entryKeyValue}(key,value)")};
|
1720
|
-
#{@entry_set.replace}(&self->entries, entry);
|
1721
|
-
#{@entry.dtor("entry")};
|
1722
|
-
}
|
1723
|
-
#{define} int #{remove}(#{type}* self, #{key.type} key) {
|
1724
|
-
int removed;
|
1725
|
-
#{@entry.type} entry;
|
1726
|
-
#{assert}(self);
|
1727
|
-
entry = #{@entry.assign("#{entryKeyOnly}(key)")};
|
1728
|
-
removed = #{@entry_set.remove}(&self->entries, entry);
|
1729
|
-
#{@entry.dtor("entry")};
|
1730
|
-
return removed;
|
1731
|
-
}
|
1732
|
-
#{define} void #{itCtor}(#{it}* self, #{type}* map) {
|
1733
|
-
#{assert}(self);
|
1734
|
-
#{assert}(map);
|
1735
|
-
#{@entry_set.itCtor}(&self->it, &map->entries);
|
1736
|
-
}
|
1737
|
-
#{define} int #{itHasNext}(#{it}* self) {
|
1738
|
-
#{assert}(self);
|
1739
|
-
return #{@entry_set.itHasNext}(&self->it);
|
1740
|
-
}
|
1741
|
-
#{define} #{key.type} #{itNextKey}(#{it}* self) {
|
1742
|
-
#{assert}(self);
|
1743
|
-
return #{@entry_set.itNext}(&self->it).key;
|
1744
|
-
}
|
1745
|
-
#{define} #{value.type} #{itNextValue}(#{it}* self) {
|
1746
|
-
#{assert}(self);
|
1747
|
-
return #{@entry_set.itNext}(&self->it).value;
|
1748
|
-
}
|
1749
|
-
#{define} #{@entry.type} #{itNext}(#{it}* self) {
|
1750
|
-
#{assert}(self);
|
1751
|
-
return #{@entry_set.itNext}(&self->it);
|
1752
|
-
}
|
1753
|
-
$
|
1754
|
-
stream << %$
|
1755
|
-
#{define} void #{dumpStats}(#{type}* self, FILE* file) {
|
1756
|
-
#{assert}(self);
|
1757
|
-
#{assert}(file);
|
1758
|
-
#{@entry_set.dumpStats}(&self->entries, file);
|
1759
|
-
}
|
1760
|
-
$ if $debug
|
1761
|
-
end
|
1762
|
-
protected
|
1763
|
-
# :nodoc:
|
1764
|
-
class EntryType < DataStructBuilder::Type
|
1765
|
-
include Assignable, Destructible, Hashable, EqualityTestable
|
1766
|
-
end # EntryType
|
1767
|
-
# :nodoc:
|
1768
|
-
class KeyType < DataStructBuilder::Type
|
1769
|
-
include Assignable, Destructible, Hashable, EqualityTestable
|
1770
|
-
end # KeyType
|
1771
|
-
# :nodoc:
|
1772
|
-
class ValueType < DataStructBuilder::Type
|
1773
|
-
include Assignable, Destructible
|
1774
|
-
end # ValueType
|
1775
|
-
# :nodoc:
|
1776
|
-
def new_entry_type
|
1777
|
-
EntryType.new(@entry_hash)
|
1778
|
-
end
|
1779
|
-
# :nodoc:
|
1780
|
-
def new_key_type(type)
|
1781
|
-
KeyType.new(type)
|
1782
|
-
end
|
1783
|
-
# :nodoc:
|
1784
|
-
def new_value_type(type)
|
1785
|
-
ValueType.new(type)
|
1786
|
-
end
|
1787
|
-
# :nodoc:
|
1788
|
-
def new_entry_set
|
1789
|
-
HashSet.new("#{type}Set", @entry_hash)
|
1790
|
-
end
|
1791
|
-
end # Map
|
1792
|
-
|
1793
|
-
|
1794
|
-
end # DataStructBuilder
|