autoc 0.8

Sign up to get free protection for your applications and to get access to all the features.
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