autoc 1.2 → 1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/README +3 -1
  4. data/doc/AutoC.html +23 -7
  5. data/doc/AutoC/Code.html +3 -3
  6. data/doc/AutoC/Collection.html +289 -76
  7. data/doc/AutoC/HashMap.html +44 -46
  8. data/doc/AutoC/HashSet.html +20 -17
  9. data/doc/AutoC/List.html +56 -92
  10. data/doc/AutoC/Module.html +2 -2
  11. data/doc/AutoC/Module/File.html +2 -2
  12. data/doc/AutoC/Module/Header.html +6 -4
  13. data/doc/AutoC/Module/Source.html +26 -26
  14. data/doc/AutoC/Priority.html +2 -2
  15. data/doc/AutoC/Queue.html +30 -92
  16. data/doc/AutoC/Reference.html +217 -61
  17. data/doc/AutoC/String.html +1393 -0
  18. data/doc/AutoC/Type.html +240 -128
  19. data/doc/AutoC/UserDefinedType.html +688 -47
  20. data/doc/AutoC/Vector.html +154 -62
  21. data/doc/_index.html +9 -2
  22. data/doc/class_list.html +1 -1
  23. data/doc/file.CHANGES.html +10 -2
  24. data/doc/file.README.html +5 -3
  25. data/doc/index.html +5 -3
  26. data/doc/method_list.html +235 -97
  27. data/doc/top-level-namespace.html +2 -2
  28. data/lib/autoc.rb +3 -1
  29. data/lib/autoc/code.rb +3 -2
  30. data/lib/autoc/collection.rb +36 -40
  31. data/lib/autoc/collection/hash_map.rb +10 -14
  32. data/lib/autoc/collection/hash_set.rb +12 -11
  33. data/lib/autoc/collection/list.rb +21 -11
  34. data/lib/autoc/collection/queue.rb +5 -8
  35. data/lib/autoc/collection/vector.rb +28 -12
  36. data/lib/autoc/string.rb +492 -0
  37. data/lib/autoc/type.rb +155 -66
  38. data/test/test.rb +157 -35
  39. data/test/test_char_string.rb +270 -0
  40. data/test/test_int_list.rb +35 -0
  41. data/test/test_int_vector.rb +34 -0
  42. data/test/test_value_hash_map.rb +162 -0
  43. data/test/test_value_hash_set.rb +173 -0
  44. data/test/test_value_list.rb +193 -0
  45. data/test/test_value_queue.rb +275 -0
  46. data/test/test_value_vector.rb +155 -0
  47. data/test/value.rb +80 -0
  48. metadata +15 -8
  49. data/test/test.c +0 -1041
  50. data/test/test.h +0 -41
  51. data/test/test_auto.c +0 -3407
  52. data/test/test_auto.h +0 -765
@@ -103,9 +103,9 @@
103
103
  </div>
104
104
 
105
105
  <div id="footer">
106
- Generated on Sat Nov 22 16:58:03 2014 by
106
+ Generated on Thu Mar 17 13:32:50 2016 by
107
107
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
108
- 0.8.7.6 (ruby-2.1.5).
108
+ 0.8.7.6 (ruby-2.2.4).
109
109
  </div>
110
110
 
111
111
  </body>
@@ -5,6 +5,7 @@
5
5
  . {AutoC::Code} generic C multi-source module generator.
6
6
  . {AutoC::Collection} strongly-typed data structure generators similar
7
7
  to the C++ STL container classes.
8
+ . {AutoC::String} wrapper around the standard C string with string building capability.
8
9
 
9
10
  == Versioning scheme
10
11
 
@@ -21,12 +22,13 @@ Should the major incompatible changes be made, the new release 2.0 will be intro
21
22
 
22
23
  =end
23
24
  module AutoC
24
- VERSION = "1.2"
25
+ VERSION = "1.3"
25
26
  end # AutoC
26
27
 
27
28
 
28
29
  require "autoc/code"
29
30
  require "autoc/type"
31
+ require "autoc/string"
30
32
  require "autoc/collection"
31
33
  require "autoc/collection/list"
32
34
  require "autoc/collection/queue"
@@ -21,7 +21,7 @@ module AutoC
21
21
  # Throw NameError is resulting string is not a valid C identifier.
22
22
  def self.c_id(obj)
23
23
  obj = obj.to_s
24
- #raise NameError.new("#{obj} is not a valid C identifier", obj) if (/^[_a-zA-Z]\w*$/ =~ obj).nil?
24
+ raise NameError.new("'#{obj}' is not a valid C identifier", obj) if (/^[_a-zA-Z]\w*$/ =~ obj).nil?
25
25
  obj
26
26
  end
27
27
 
@@ -50,7 +50,7 @@ class Code
50
50
  end
51
51
  end
52
52
  def source_size
53
- s = String.new
53
+ s = ::String.new
54
54
  write_decls(s)
55
55
  write_defs(s)
56
56
  s.size
@@ -187,6 +187,7 @@ class Module::Header < Module::File
187
187
  stream << %$
188
188
  #endif
189
189
  $
190
+ stream << "\n" # DigitalMars C in strict ANSI (-A) mode complains about absent empty line at the very end so let's make it happy
190
191
  end
191
192
 
192
193
  end # Header
@@ -72,6 +72,8 @@ WARNING: the collection being iterated *must not* be modified in any way otherwi
72
72
  =end
73
73
  class Collection < Type
74
74
 
75
+ include Redirecting
76
+
75
77
  attr_reader :element, :it_ref
76
78
 
77
79
  def hash; super ^ element.hash end
@@ -86,55 +88,49 @@ class Collection < Type
86
88
  super(type_name, visibility)
87
89
  @it_ref = "#{it}*"
88
90
  @element = Type.coerce(element_type)
89
- @ctor = define_function(:ctor, Function::Signature.new([type_ref^:self]))
90
- @dtor = define_function(:dtor, Function::Signature.new([type_ref^:self]))
91
- @copy = define_function(:copy, Function::Signature.new([type_ref^:dst, type_ref^:src]))
92
- @equal = define_function(:equal, Function::Signature.new([type_ref^:lt, type_ref^:rt], :int))
93
- @identify = define_function(:identify, Function::Signature.new([type_ref^:self], :size_t))
94
- @less = define_function(:less, Function::Signature.new([type_ref^:lt, type_ref^:rt], :int))
95
- element_type_check(element)
91
+ initialize_redirectors
92
+ element_requirement(element)
96
93
  end
97
94
 
98
- def write_intf_decls(stream, declare, define)
99
- # Emit default redirection macros
100
- # Unlike other special methods the constructors may have extra arguments
101
- # Assume the constructor's first parameter is always a target
102
- ctor_ex = ctor.parameters.names[1..-1]
103
- ctor_lt = ["self"].concat(ctor_ex).join(',')
104
- ctor_rt = ["&self"].concat(ctor_ex).join(',')
105
- stream << %$
106
- #define _#{ctor}(#{ctor_lt}) #{ctor}(#{ctor_rt})
107
- #define _#{dtor}(self) #{dtor}(&self)
108
- #define _#{identify}(self) #{identify}(&self)
109
- #define _#{copy}(dst,src) #{copy}(&dst,&src)
110
- #define _#{equal}(lt,rt) #{equal}(&lt,&rt)
111
- #define _#{less}(lt,rt) #{less}(&lt,&rt)
112
- $
95
+ # Normally all collections are expected to provide all special functions
96
+ # If a collection does not provide specific function it should override the respective method
97
+
98
+ # Collection always has default constructor
99
+ def constructible?; true end
100
+
101
+ # Collection always has constructor
102
+ def initializable?; true end
103
+
104
+ # Collection always has destructor but the element is required to be destructible on its own
105
+ # because collection destruction incurs destruction of all contained elements
106
+ def destructible?; true && element.destructible? end
107
+
108
+ # Collection always has copy constructor but the element is required to be copyable on its own
109
+ # because collection copying incurs copying of all contained elements
110
+ def copyable?; true && element.copyable? end
111
+
112
+ # Collection always has equality tester but the element is required to be comparable on its own
113
+ # because collection comparison incurs comparison of all contained elements
114
+ def comparable?; true && element.comparable? end
115
+
116
+ # So far there are no orderable collections therefore inherit false-returning #orderable?
117
+
118
+ # Collection always has hash calculation function but the element is required to be hashable on its own
119
+ # because collection comparison incurs hash calculation for all contained elements
120
+ def hashable?
121
+ # Since using collection as an element of a hash-based container also requires it to be comparable as well
122
+ comparable? && element.hashable?
113
123
  end
114
124
 
115
- def copyable?; super && element.copyable? end
116
-
117
- def comparable?; super && element.comparable? end
118
-
119
- def hashable?; super && element.hashable? end
125
+ def write_intf_decls(stream, declare, define)
126
+ write_redirectors(stream, declare, define)
127
+ end
120
128
 
121
129
  private
122
130
 
123
- def element_type_check(obj)
131
+ def element_requirement(obj)
124
132
  raise "type #{obj.type} (#{obj}) must be destructible" unless obj.destructible?
125
133
  raise "type #{obj.type} (#{obj}) must be copyable" unless obj.copyable?
126
- raise "type #{obj.type} (#{obj}) must be comparable" unless obj.comparable?
127
- raise "type #{obj.type} (#{obj}) must be hashable" unless obj.hashable?
128
- end
129
-
130
- # @private
131
- class Redirector < Function
132
- # Redirect call to the specific macro
133
- def call(*params) "_#{name}(" + params.join(',') + ')' end
134
- end # Redirector
135
-
136
- def define_function(name, signature)
137
- Redirector.new(method_missing(name), signature)
138
134
  end
139
135
 
140
136
  end # Collection
@@ -60,7 +60,7 @@ Return non-zero value if map +self+ contains no entries and zero value otherwise
60
60
  |
61
61
  Return a _copy_ of the element in +self+ bound to a key which is considered equal to the key +key+.
62
62
 
63
- WARNING: +self+ *must* contain such key otherwise the behavior is undefined. See ~type~Contains().
63
+ WARNING: +self+ *must* contain such key otherwise the behavior is undefined. See ~type~ContainsKey().
64
64
 
65
65
  |*_void_* ~type~Purge(*_Type_* * +self+)
66
66
  |
@@ -77,7 +77,7 @@ Return non-zero value on successful put and zero value otherwise.
77
77
  If +self+ contains a key which is considered equal to the key +key+,
78
78
  remove and destroy that key along with an element bound to it
79
79
  and put a new pair built of the _copies_ of +key+ and +value+,
80
- otherwise simply put a new key/element pair into +self+ in the way of ~type~Put().
80
+ otherwise no nothing.
81
81
 
82
82
  Return non-zero value if the replacement was actually performed and zero value otherwise.
83
83
 
@@ -146,22 +146,18 @@ class HashMap < Collection
146
146
  @key = Type.coerce(key_type)
147
147
  @entry = UserDefinedType.new(:type => entry, :identify => entryIdentify, :equal => entryEqual, :copy => entryCopy, :dtor => entryDtor)
148
148
  @set = HashSet.new(set, @entry, :static)
149
- @capability.subtract [:orderable]
150
- element_type_check(value)
151
- key_type_check(key)
149
+ element_requirement(value)
150
+ key_requirement(key)
152
151
  end
153
-
152
+
154
153
  def copyable?; super && key.copyable? end
155
154
 
156
155
  def comparable?; super && key.comparable? end
157
156
 
158
- def hashable?
159
- # NOTE : must be in sync with Type#hashable?
160
- # No super call here because the map's element need not to be hashable,- only the key must be
161
- @capability.include?(:hashable) && comparable? && key.hashable?
162
- end
157
+ def hashable?; super && key.hashable? end
163
158
 
164
159
  def write_intf_types(stream)
160
+ super
165
161
  stream << %$
166
162
  /***
167
163
  **** #{type}<#{key.type},#{value.type}> (#{self.class})
@@ -213,6 +209,7 @@ class HashMap < Collection
213
209
  end
214
210
 
215
211
  def write_impls(stream, define)
212
+ super
216
213
  stream << %$
217
214
  #define AUTOC_VALID_VALUE 1
218
215
  #define AUTOC_VALID_KEY 2
@@ -287,9 +284,8 @@ class HashMap < Collection
287
284
  int absent;
288
285
  #{assert}(self);
289
286
  #{assert}(entry);
290
- if((absent = !#{containsKey}(self, entry->key))) {
291
- #{@set.put}(&self->entries, *entry);
292
- }
287
+ absent = !#{containsKey}(self, entry->key);
288
+ if(absent) #{@set.put}(&self->entries, *entry);
293
289
  return absent;
294
290
  }
295
291
  #{define} #{copy.definition} {
@@ -70,11 +70,11 @@ Remove and destroy all elements stored in +self+.
70
70
  |
71
71
  Put a _copy_ of the element +what+ into +self+ *only if* there is no such element in +self+ which is considered equal to +what+.
72
72
 
73
- Return non-zero value on successful element put and zero value otherwise.
73
+ Return non-zero value on successful element put (that is there was not such element in +self+) and zero value otherwise.
74
74
 
75
75
  |*_int_* ~type~Replace(*_Type_* * +self+, *_E_* +with+)
76
76
  |
77
- *If* +self+ contains an element which is considered equal to the element +with+,
77
+ If +self+ contains an element which is considered equal to the element +with+,
78
78
  replace that element with a _copy_ of +with+, otherwise do nothing.
79
79
  Replaced element is destroyed.
80
80
 
@@ -148,11 +148,11 @@ class HashSet < Collection
148
148
  def initialize(*args)
149
149
  super
150
150
  @list = List.new(list, element, :static)
151
- @capability.subtract [:orderable]
152
- key_type_check(element)
151
+ key_requirement(element)
153
152
  end
154
153
 
155
154
  def write_intf_types(stream)
155
+ super
156
156
  stream << %$
157
157
  /***
158
158
  **** #{type}<#{element.type}> (#{self.class})
@@ -170,7 +170,7 @@ class HashSet < Collection
170
170
  };
171
171
  struct #{it} {
172
172
  #{type_ref} set;
173
- int bucket_index;
173
+ size_t bucket_index;
174
174
  #{@list.it} it;
175
175
  };
176
176
  $
@@ -203,10 +203,11 @@ class HashSet < Collection
203
203
  end
204
204
 
205
205
  def write_impls(stream, define)
206
+ super
206
207
  @list.write_intf_decls(stream, static, inline)
207
208
  @list.write_impls(stream, static)
208
209
  stream << %$
209
- #{define} #{element.type_ref} #{itGetRef}(#{it_ref});
210
+ static #{element.type_ref} #{itGetRef}(#{it_ref});
210
211
  static void #{rehash}(#{type_ref} self) {
211
212
  #{@list.type_ref} buckets;
212
213
  size_t index, bucket_count, size, fill;
@@ -407,11 +408,11 @@ class HashSet < Collection
407
408
  #{define} void #{itCtor}(#{it_ref} self, #{type_ref} set) {
408
409
  #{assert}(self);
409
410
  self->set = set;
410
- self->bucket_index = -1;
411
+ self->bucket_index = self->set->bucket_count;
411
412
  }
412
413
  #{define} int #{itMove}(#{it_ref} self) {
413
414
  #{assert}(self);
414
- if(self->bucket_index < 0) #{@list.itCtor}(&self->it, &self->set->buckets[self->bucket_index = 0]);
415
+ if(self->bucket_index >= self->set->bucket_count) #{@list.itCtor}(&self->it, &self->set->buckets[self->bucket_index = 0]);
415
416
  if(#{@list.itMove}(&self->it)) return 1;
416
417
  while(++self->bucket_index < self->set->bucket_count) {
417
418
  #{@list.itCtor}(&self->it, &self->set->buckets[self->bucket_index]);
@@ -423,7 +424,7 @@ class HashSet < Collection
423
424
  #{assert}(self);
424
425
  return #{@list.itGet}(&self->it);
425
426
  }
426
- #{define} #{element.type_ref} #{itGetRef}(#{it_ref} self) {
427
+ static #{element.type_ref} #{itGetRef}(#{it_ref} self) {
427
428
  #{assert}(self);
428
429
  return #{@list.itGetRef}(&self->it);
429
430
  }
@@ -432,9 +433,9 @@ class HashSet < Collection
432
433
 
433
434
  private
434
435
 
435
- def key_type_check(obj)
436
+ def key_requirement(obj)
437
+ element_requirement(obj)
436
438
  raise "type #{obj.type} (#{obj}) must be hashable" unless obj.hashable?
437
- element_type_check(obj)
438
439
  end
439
440
 
440
441
  end # HashSet
@@ -7,7 +7,7 @@ module AutoC
7
7
  =begin
8
8
 
9
9
  List is an ordered unidirectional sequence container.
10
- List supports submission/polling operations at one end hence it can be used as a LIFO container.
10
+ List supports submission/polling operations on one end hence it can be used as a LIFO container (a stack).
11
11
 
12
12
  The collection's C++ counterpart is +std::forward_list<>+ template class.
13
13
 
@@ -154,12 +154,8 @@ WARNING: current position *must* be valid otherwise the behavior is undefined. S
154
154
  =end
155
155
  class List < Collection
156
156
 
157
- def initialize(*args)
158
- super
159
- @capability.subtract [:orderable]
160
- end
161
-
162
157
  def write_intf_types(stream)
158
+ super
163
159
  stream << %$
164
160
  /***
165
161
  **** #{type}<#{element.type}> (#{self.class})
@@ -214,8 +210,9 @@ class List < Collection
214
210
  end
215
211
 
216
212
  def write_impls(stream, define)
213
+ super
217
214
  stream << %$
218
- #{define} #{element.type_ref} #{itGetRef}(#{it_ref});
215
+ static #{element.type_ref} #{itGetRef}(#{it_ref});
219
216
  #{define} #{ctor.definition} {
220
217
  #{assert}(self);
221
218
  self->head_node = NULL;
@@ -234,12 +231,22 @@ class List < Collection
234
231
  }
235
232
  #{define} #{copy.definition} {
236
233
  #{it} it;
234
+ size_t index, size;
235
+ #{element.type}** elements;
237
236
  #{assert}(src);
238
237
  #{assert}(dst);
239
238
  #{ctor}(dst);
240
- #{itCtor}(&it, src);
241
- while(#{itMove}(&it)) {
242
- #{push}(dst, *#{itGetRef}(&it));
239
+ if(!#{empty}(src)) {
240
+ /* List is a LIFO type container therefore the insertion order into the destination container should be reversed */
241
+ elements = (#{element.type}**)#{malloc}((size = #{size}(src))*sizeof(#{element.type}*)); #{assert}(elements);
242
+ index = 0;
243
+ #{itCtor}(&it, src);
244
+ while(#{itMove}(&it)) {
245
+ #{assert}(index < size);
246
+ elements[index++] = #{itGetRef}(&it);
247
+ }
248
+ for(index = size; index > 0; --index) #{push}(dst, *elements[index-1]); /* Be careful not to run into the underflow of the unsigned integer type */
249
+ #{free}(elements);
243
250
  }
244
251
  }
245
252
  #{define} #{equal.definition} {
@@ -331,6 +338,9 @@ class List < Collection
331
338
  }
332
339
  #{abort}();
333
340
  }
341
+ /* FIXME: for the generality's sake there should be both `what` and `with` values
342
+ This is not achievable without breaking the interface, however,
343
+ therefore defer this change to the major version bump */
334
344
  #{define} int #{replaceEx}(#{type_ref} self, #{element.type} with, int count) {
335
345
  #{node}* node;
336
346
  int replaced = 0;
@@ -403,7 +413,7 @@ class List < Collection
403
413
  #{element.copy("result", "self->this_node->element")};
404
414
  return result;
405
415
  }
406
- #{define} #{element.type_ref} #{itGetRef}(#{it_ref} self) {
416
+ static #{element.type_ref} #{itGetRef}(#{it_ref} self) {
407
417
  #{assert}(self);
408
418
  #{assert}(self->this_node);
409
419
  return &self->this_node->element;
@@ -9,7 +9,7 @@ module AutoC
9
9
  Queue is an ordered bidirectional sequence container.
10
10
  Queue supports addition/removal operations at both ends.
11
11
  However, it is intended to be used as a FIFO container as opposed to {AutoC::List}
12
- since submission and polling operations are performed on the opposite ends.
12
+ therefore the default submission, polling and retrieval operations are performed on the opposite ends.
13
13
 
14
14
  This collection is a synergy of C++ +std::list<>+ and +std::queue<>+ template classes.
15
15
 
@@ -193,12 +193,8 @@ WARNING: current position *must* be valid otherwise the behavior is undefined. S
193
193
  =end
194
194
  class Queue < Collection
195
195
 
196
- def initialize(*args)
197
- super
198
- @capability.subtract [:orderable]
199
- end
200
-
201
196
  def write_intf_types(stream)
197
+ super
202
198
  stream << %$
203
199
  /***
204
200
  **** #{type}<#{element.type}> (#{self.class})
@@ -263,8 +259,9 @@ class Queue < Collection
263
259
  end
264
260
 
265
261
  def write_impls(stream, define)
262
+ super
266
263
  stream << %$
267
- #{define} #{element.type_ref} #{itGetRef}(#{it_ref});
264
+ static #{element.type_ref} #{itGetRef}(#{it_ref});
268
265
  #{define} #{ctor.definition} {
269
266
  #{assert}(self);
270
267
  self->head_node = self->tail_node = NULL;
@@ -506,7 +503,7 @@ class Queue < Collection
506
503
  #{element.copy("result", "self->this_node->element")};
507
504
  return result;
508
505
  }
509
- #{define} #{element.type_ref} #{itGetRef}(#{it_ref} self) {
506
+ static #{element.type_ref} #{itGetRef}(#{it_ref} self) {
510
507
  #{assert}(self);
511
508
  #{assert}(self->this_node);
512
509
  return &self->this_node->element;
@@ -78,9 +78,17 @@ Return number of elements stored in vector +self+.
78
78
 
79
79
  |*_void_* ~type~Sort(*_Type_* * +self+)
80
80
  |
81
+ Perform an ascending sort.
82
+ See ~type~SortEx().
83
+
84
+ NOTE : optional operation.
85
+
86
+ |*_void_* ~type~SortEx(*_Type_* * +self+, *_int_* ascending)
87
+ |
81
88
  NOTE : optional operation.
82
89
 
83
- Perform a sorting operation on the contents of vector +self+ utilizing either generated of user supplied ordering functions.
90
+ Perform a sort operation on the contents of vector +self+ utilizing either generated of user supplied ordering functions.
91
+ If the +ascending+ is non-zero, perform the sorting in ascending order otherwise perform the soring in descending order.
84
92
 
85
93
  Note that this operation is defined only if element type is orderable, e.g. has equality testing and comparison operations defined.
86
94
 
@@ -124,12 +132,15 @@ class Vector < Collection
124
132
  def initialize(*args)
125
133
  super
126
134
  # Override the default type constructor as the Vector's requires one extra parameter
127
- # Note that this makes the Vector instance un-constructible
128
- @ctor = define_function(:ctor, Function::Signature.new([type_ref^:self, :size_t^:element_count]))
129
- @capability.subtract [:constructible, :orderable] # No default constructor and no less operation defined
135
+ # Note that this makes the Vector instance non-constructible
136
+ @ctor = define_redirector(:ctor, Function::Signature.new([type_ref^:self, :size_t^:element_count]))
130
137
  end
131
138
 
139
+ # No default constructor provided
140
+ def constructible?; false end
141
+
132
142
  def write_intf_types(stream)
143
+ super
133
144
  stream << %$
134
145
  /***
135
146
  **** #{type}<#{element.type}> (#{self.class})
@@ -144,8 +155,7 @@ class Vector < Collection
144
155
  };
145
156
  struct #{it} {
146
157
  #{type_ref} vector;
147
- int index;
148
- int forward;
158
+ int index, forward;
149
159
  };
150
160
  $
151
161
  end
@@ -156,6 +166,7 @@ class Vector < Collection
156
166
  #{declare} #{ctor.declaration};
157
167
  #{declare} #{dtor.declaration};
158
168
  #{declare} #{copy.declaration};
169
+ /* TODO #{copyRange}() */
159
170
  #{declare} #{equal.declaration};
160
171
  #{declare} #{identify.declaration};
161
172
  #{declare} void #{resize}(#{type_ref}, size_t);
@@ -199,11 +210,13 @@ class Vector < Collection
199
210
  }
200
211
  $
201
212
  stream << %$
202
- #{declare} void #{sort}(#{type_ref});
213
+ #define #{sort}(self) #{sortEx}(self, 1)
214
+ #{declare} void #{sortEx}(#{type_ref}, int);
203
215
  $ if element.orderable?
204
216
  end
205
217
 
206
218
  def write_impls(stream, define)
219
+ super
207
220
  stream << %$
208
221
  static void #{allocate}(#{type_ref} self, size_t element_count) {
209
222
  #{assert}(self);
@@ -283,7 +296,7 @@ class Vector < Collection
283
296
  }
284
297
  $
285
298
  stream << %$
286
- static int #{comparator}(void* lp_, void* rp_) {
299
+ static int #{ascend}(void* lp_, void* rp_) {
287
300
  #{element.type_ref} lp = (#{element.type_ref})lp_;
288
301
  #{element.type_ref} rp = (#{element.type_ref})rp_;
289
302
  if(#{element.equal("*lp", "*rp")}) {
@@ -294,18 +307,21 @@ class Vector < Collection
294
307
  return +1;
295
308
  }
296
309
  }
297
- #{define} void #{sort}(#{type_ref} self) {
310
+ static int #{descend}(void* lp_, void* rp_) {
311
+ return -#{ascend}(lp_, rp_);
312
+ }
313
+ #{define} void #{sortEx}(#{type_ref} self, int ascending) {
298
314
  typedef int (*F)(const void*, const void*);
299
315
  #{assert}(self);
300
- qsort(self->values, #{size}(self), sizeof(#{element.type}), (F)#{comparator});
316
+ qsort(self->values, #{size}(self), sizeof(#{element.type}), ascending ? (F)#{ascend} : (F)#{descend});
301
317
  }
302
318
  $ if element.orderable?
303
319
  end
304
320
 
305
321
  private
306
322
 
307
- def element_type_check(obj)
308
- # Additional requirement is imposed on the vector's element
323
+ def element_requirement(obj)
324
+ # Vector requires the element to have default parameterless constructor
309
325
  raise "type #{obj.type} (#{obj}) must be constructible" unless obj.constructible?
310
326
  super
311
327
  end