autoc 0.8

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.
data/README ADDED
@@ -0,0 +1,13 @@
1
+ AutoC -- a host of Ruby modules related to automatic C source code generation.
2
+ AutoC is a free software distributed under the terms of modified BSD license.
3
+
4
+ Project home page is http://autoc.sourceforge.net/
5
+
6
+ For offline user documentation refer to manual/manual.pdf
7
+
8
+ Ad-hoc test build instructions:
9
+ cd test
10
+ cc -o test test.c test_auto.c
11
+
12
+ That's all for now, folks! Stay tuned.
13
+ Oleg A. Khlybov <fougas@mail.ru>
@@ -0,0 +1,12 @@
1
+ =begin rdoc
2
+ = AutoC documentation home
3
+
4
+ *AutoC* is a host of Ruby modules related to automatic C source code generation.
5
+
6
+ [CodeBuilder] Generic C multi-source module generator.
7
+ [DataStructBuilder] Strongly-typed data structure generators akin the C++ STL container classes.
8
+ =end
9
+
10
+
11
+ require "autoc/code_builder"
12
+ require "autoc/data_struct_builder"
@@ -0,0 +1,247 @@
1
+ require "set"
2
+
3
+
4
+ module CodeBuilder
5
+
6
+
7
+ # class Entity
8
+ # def entities()
9
+ # def priority()
10
+ # def source_size()
11
+ # def attach(source)
12
+ # def write_intf(stream)
13
+ # def write_defs(stream)
14
+ # def write_decls(stream)
15
+ # def hash()
16
+ # def eql?(other)
17
+ # end
18
+
19
+
20
+ # TODO min/max Fixnums
21
+ module Priority
22
+ DEFAULT = 0
23
+ MIN = -1000
24
+ MAX = +1000
25
+ end
26
+
27
+
28
+ # A no-op entity implementation with reasonable defaults
29
+ class Code
30
+ def entities; [] end
31
+ def priority
32
+ if entities.empty?
33
+ Priority::DEFAULT
34
+ else
35
+ result = Priority::DEFAULT
36
+ entities.each do |e|
37
+ ep = e.priority
38
+ result = ep if result > ep
39
+ end
40
+ result-1
41
+ end
42
+ end
43
+ def source_size
44
+ s = String.new
45
+ write_decls(s)
46
+ write_defs(s)
47
+ s.size
48
+ end
49
+ def attach(source) source << self if source.smallest? end
50
+ def write_intf(stream) end
51
+ def write_defs(stream) end
52
+ def write_decls(stream) end
53
+ end # Code
54
+
55
+
56
+ class Module
57
+
58
+ attr_reader :header, :smallest_source, :main_source
59
+
60
+ def initialize
61
+ @entities = Set.new
62
+ @source_size_threshold = 0
63
+ end
64
+
65
+ def <<(obj)
66
+ unless @entities.include?(obj)
67
+ @entities << obj
68
+ obj.entities.each {|e| self << e}
69
+ end
70
+ self
71
+ end
72
+
73
+ # def new_header()
74
+
75
+ # def new_source(index)
76
+
77
+ def source_count=(count)
78
+ @source_count = count
79
+ end
80
+
81
+ def generate!
82
+ @header = new_header
83
+ @sources = []
84
+ (1..source_count).each {|i| @sources << new_source(i)}
85
+ @main_source = @sources.first
86
+ @smallest_source = @main_source
87
+ # It appears that computing the size of a source might be a fairly expensive operation so do it only when neccessary
88
+ refresh_smallest_source = source_count > 1
89
+ @entities.each do |e|
90
+ @header << e
91
+ @smallest_source = @sources.sort_by {|s| s.size}.first if refresh_smallest_source
92
+ @sources.each {|s| e.attach(s)}
93
+ end
94
+ @header.generate
95
+ @sources.each {|s| s.generate}
96
+ end
97
+
98
+ def source_count
99
+ if @source_count.nil?
100
+ total = 0
101
+ @entities.each {|e| total += e.source_size}
102
+ count = @source_size_threshold > 0 ? (total/@source_size_threshold + 1) : 1
103
+ @source_count = count > 0 ? count : 1
104
+ else
105
+ @source_count
106
+ end
107
+ end
108
+
109
+ end # Module
110
+
111
+
112
+ def self.priority_sort(entities, reverse = false)
113
+ list = entities.to_a.sort_by!{|e| e.priority}
114
+ list.reverse! unless reverse
115
+ list
116
+ end # priority_sort
117
+
118
+
119
+ class File
120
+
121
+ attr_reader :entities
122
+
123
+ # def new_stream()
124
+
125
+ # def write(stream)
126
+
127
+ def initialize(m)
128
+ @entities = Set.new
129
+ @module = m
130
+ end
131
+
132
+ def generate
133
+ stream = new_stream
134
+ begin
135
+ write(stream)
136
+ ensure
137
+ stream.close
138
+ end
139
+ end
140
+
141
+ def <<(e)
142
+ @entities << e
143
+ self
144
+ end
145
+
146
+ end # File
147
+
148
+
149
+ class Header < File
150
+ def write(stream)
151
+ CodeBuilder.priority_sort(entities).each {|e| e.write_intf(stream)}
152
+ end
153
+ end # Header
154
+
155
+
156
+ class Source < File
157
+
158
+ attr_reader :index
159
+
160
+ def initialize(m, i)
161
+ super(m)
162
+ @index = i
163
+ end
164
+
165
+ def write(stream)
166
+ sorted = CodeBuilder.priority_sort(entities)
167
+ sorted.each {|e| e.write_decls(stream)}
168
+ sorted.each {|e| e.write_defs(stream)}
169
+ end
170
+
171
+ def main?
172
+ equal?(@module.main_source)
173
+ end
174
+
175
+ def smallest?
176
+ equal?(@module.smallest_source)
177
+ end
178
+
179
+ def size
180
+ size = 0
181
+ @entities.each {|e| size += e.source_size}
182
+ size
183
+ end
184
+
185
+ end # Source
186
+
187
+
188
+ class CModule < CodeBuilder::Module
189
+ def self.generate!(name, &block)
190
+ m = self.new(name)
191
+ block.call(m)
192
+ m.generate!
193
+ end
194
+ attr_reader :name
195
+ def initialize(name)
196
+ super()
197
+ @name = name.to_s # TODO validate
198
+ end
199
+ def new_header
200
+ Header.new(self)
201
+ end
202
+ def new_source(index)
203
+ Source.new(self, index)
204
+ end
205
+ class Header < CodeBuilder::Header
206
+ attr_reader :file_name
207
+ def initialize(*args)
208
+ super
209
+ @file_name = "#{@module.name.downcase}_auto.h"
210
+ @guard_macro = "#{@module.name.upcase}_AUTO_H"
211
+ end
212
+ def new_stream
213
+ ::File.new(@file_name, "wt")
214
+ end
215
+ def write(stream)
216
+ stream << %$
217
+ /* AUTOMATICALLY GENERATED HEADER FILE. DO NOT MODIFY. */
218
+ #ifndef #{@guard_macro}
219
+ #define #{@guard_macro}
220
+ $
221
+ super
222
+ stream << %$
223
+ #endif
224
+ $
225
+ end
226
+ end # Header
227
+ class Source < CodeBuilder::Source
228
+ attr_reader :file_name
229
+ def initialize(*args)
230
+ super
231
+ @file_name = @module.source_count > 1 ? "#{@module.name.downcase}_auto#{index}.c" : "#{@module.name.downcase}_auto.c"
232
+ end
233
+ def new_stream
234
+ ::File.new(@file_name, "wt")
235
+ end
236
+ def write(stream)
237
+ stream << %$
238
+ /* AUTOMATICALLY GENERATED SOURCE FILE. DO NOT MODIFY. */
239
+ #include "#{@module.header.file_name}"
240
+ $
241
+ super
242
+ end
243
+ end # Source
244
+ end # Module
245
+
246
+
247
+ end # CodeBuilder
@@ -0,0 +1,1794 @@
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