Upgrade to 1.46.0
[platform/upstream/nghttp2.git] / third-party / mruby / mrblib / array.rb
1 # coding: utf-8
2 ##
3 # Array
4 #
5 # ISO 15.2.12
6 class Array
7
8   ##
9   # Calls the given block for each element of +self+
10   # and pass the respective element.
11   #
12   # ISO 15.2.12.5.10
13   # def each(&block)
14   #   return to_enum :each unless block
15
16   #   idx = 0
17   #   while idx < length
18   #     block.call(self[idx])
19   #     idx += 1
20   #   end
21   #   self
22   # end
23
24   ##
25   # Calls the given block for each element of +self+
26   # and pass the index of the respective element.
27   #
28   # ISO 15.2.12.5.11
29   def each_index(&block)
30     return to_enum :each_index unless block
31
32     idx = 0
33     while idx < length
34       block.call(idx)
35       idx += 1
36     end
37     self
38   end
39
40   ##
41   # Calls the given block for each element of +self+
42   # and pass the respective element. Each element will
43   # be replaced by the resulting values.
44   #
45   # ISO 15.2.12.5.7
46   def collect!(&block)
47     return to_enum :collect! unless block
48
49     idx = 0
50     len = size
51     while idx < len
52       self[idx] = block.call self[idx]
53       idx += 1
54     end
55     self
56   end
57
58   ##
59   # Alias for collect!
60   #
61   # ISO 15.2.12.5.20
62   alias map! collect!
63
64   ##
65   # Private method for Array creation.
66   #
67   # ISO 15.2.12.5.15
68   def initialize(size=0, obj=nil, &block)
69     size = size.__to_int
70     raise ArgumentError, "negative array size" if size < 0
71
72     self.clear
73     if size > 0
74       self[size - 1] = nil # allocate
75
76       idx = 0
77       while idx < size
78         self[idx] = (block)? block.call(idx): obj
79         idx += 1
80       end
81     end
82
83     self
84   end
85
86   def _inspect(recur_list)
87     size = self.size
88     return "[]" if size == 0
89     return "[...]" if recur_list[self.object_id]
90     recur_list[self.object_id] = true
91     ary=[]
92     i=0
93     while i<size
94       ary<<self[i]._inspect(recur_list)
95       i+=1
96     end
97     "["+ary.join(", ")+"]"
98   end
99   ##
100   # Return the contents of this array as a string.
101   #
102   # ISO 15.2.12.5.31 (x)
103   def inspect
104     self._inspect({})
105   end
106   # ISO 15.2.12.5.32 (x)
107   alias to_s inspect
108
109   ##
110   #  Equality---Two arrays are equal if they contain the same number
111   #  of elements and if each element is equal to (according to
112   #  Object.==) the corresponding element in the other array.
113   #
114   # ISO 15.2.12.5.33 (x)
115   def ==(other)
116     other = self.__ary_eq(other)
117     return false if other == false
118     return true  if other == true
119     len = self.size
120     i = 0
121     while i < len
122       return false if self[i] != other[i]
123       i += 1
124     end
125     return true
126   end
127
128   ##
129   #  Returns <code>true</code> if +self+ and _other_ are the same object,
130   #  or are both arrays with the same content.
131   #
132   # ISO 15.2.12.5.34 (x)
133   def eql?(other)
134     other = self.__ary_eq(other)
135     return false if other == false
136     return true  if other == true
137     len = self.size
138     i = 0
139     while i < len
140       return false unless self[i].eql?(other[i])
141       i += 1
142     end
143     return true
144   end
145
146   ##
147   #  Comparison---Returns an integer (-1, 0, or +1)
148   #  if this array is less than, equal to, or greater than <i>other_ary</i>.
149   #  Each object in each array is compared (using <=>). If any value isn't
150   #  equal, then that inequality is the return value. If all the
151   #  values found are equal, then the return is based on a
152   #  comparison of the array lengths.  Thus, two arrays are
153   #  "equal" according to <code>Array#<=></code> if and only if they have
154   #  the same length and the value of each element is equal to the
155   #  value of the corresponding element in the other array.
156   #
157   # ISO 15.2.12.5.36 (x)
158   def <=>(other)
159     other = self.__ary_cmp(other)
160     return 0 if 0 == other
161     return nil if nil == other
162
163     len = self.size
164     n = other.size
165     len = n if len > n
166     i = 0
167     while i < len
168       n = (self[i] <=> other[i])
169       return n if n.nil? || n != 0
170       i += 1
171     end
172     len = self.size - other.size
173     if len == 0
174       0
175     elsif len > 0
176       1
177     else
178       -1
179     end
180   end
181
182   ##
183   # Delete element with index +key+
184   def delete(key, &block)
185     while i = self.index(key)
186       self.delete_at(i)
187       ret = key
188     end
189     return block.call if ret.nil? && block
190     ret
191   end
192 end
193
194 ##
195 # Array is enumerable
196 class Array
197   # ISO 15.2.12.3
198   include Enumerable
199
200   ##
201   # Sort all elements and replace +self+ with these
202   # elements.
203   def sort!(&block)
204     stack = [ [ 0, self.size - 1 ] ]
205     until stack.empty?
206       left, mid, right = stack.pop
207       if right == nil
208         right = mid
209         # sort self[left..right]
210         if left < right
211           if left + 1 == right
212             lval = self[left]
213             rval = self[right]
214             cmp = if block then block.call(lval,rval) else lval <=> rval end
215             if cmp.nil?
216               raise ArgumentError, "comparison of #{lval.inspect} and #{rval.inspect} failed"
217             end
218             if cmp > 0
219               self[left]  = rval
220               self[right] = lval
221             end
222           else
223             mid = ((left + right + 1) / 2).floor
224             stack.push [ left, mid, right ]
225             stack.push [ mid, right ]
226             stack.push [ left, (mid - 1) ] if left < mid - 1
227           end
228         end
229       else
230         lary = self[left, mid - left]
231         lsize = lary.size
232
233         # The entity sharing between lary and self may cause a large memory
234         # copy operation in the merge loop below.  This harmless operation
235         # cancels the sharing and provides a huge performance gain.
236         lary[0] = lary[0]
237
238         # merge
239         lidx = 0
240         ridx = mid
241         (left..right).each { |i|
242           if lidx >= lsize
243             break
244           elsif ridx > right
245             self[i, lsize - lidx] = lary[lidx, lsize - lidx]
246             break
247           else
248             lval = lary[lidx]
249             rval = self[ridx]
250             cmp = if block then block.call(lval,rval) else lval <=> rval end
251             if cmp.nil?
252               raise ArgumentError, "comparison of #{lval.inspect} and #{rval.inspect} failed"
253             end
254             if cmp <= 0
255               self[i] = lval
256               lidx += 1
257             else
258               self[i] = rval
259               ridx += 1
260             end
261           end
262         }
263       end
264     end
265     self
266   end
267
268   def sort(&block)
269     self.dup.sort!(&block)
270   end
271 end