51 this(underlying, length, new TreeMap<Long, Object>()); |
51 this(underlying, length, new TreeMap<Long, Object>()); |
52 } |
52 } |
53 |
53 |
54 SparseArrayData(final ArrayData underlying, final long length, final TreeMap<Long, Object> sparseMap) { |
54 SparseArrayData(final ArrayData underlying, final long length, final TreeMap<Long, Object> sparseMap) { |
55 super(length); |
55 super(length); |
56 assert underlying.length() <= length; |
56 assert underlying.length <= length; |
57 this.underlying = underlying; |
57 this.underlying = underlying; |
58 this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length()); |
58 this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length); |
59 this.sparseMap = sparseMap; |
59 this.sparseMap = sparseMap; |
60 } |
60 } |
61 |
61 |
62 @Override |
62 @Override |
63 public ArrayData copy() { |
63 public ArrayData copy() { |
64 return new SparseArrayData(underlying.copy(), length(), new TreeMap<>(sparseMap)); |
64 return new SparseArrayData(underlying.copy(), length, new TreeMap<>(sparseMap)); |
65 } |
65 } |
66 |
66 |
67 @Override |
67 @Override |
68 public Object[] asObjectArray() { |
68 public Object[] asObjectArray() { |
69 final int length = (int) Math.min(length(), Integer.MAX_VALUE); |
69 final int len = (int)Math.min(length, Integer.MAX_VALUE); |
70 final int underlyingLength = (int) Math.min(length, underlying.length()); |
70 final int underlyingLength = (int)Math.min(len, underlying.length); |
71 final Object[] objArray = new Object[length]; |
71 final Object[] objArray = new Object[len]; |
72 |
72 |
73 for (int i = 0; i < underlyingLength; i++) { |
73 for (int i = 0; i < underlyingLength; i++) { |
74 objArray[i] = underlying.getObject(i); |
74 objArray[i] = underlying.getObject(i); |
75 } |
75 } |
76 |
76 |
77 Arrays.fill(objArray, underlyingLength, length, ScriptRuntime.UNDEFINED); |
77 Arrays.fill(objArray, underlyingLength, len, ScriptRuntime.UNDEFINED); |
78 |
78 |
79 for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) { |
79 for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) { |
80 final long key = entry.getKey(); |
80 final long key = entry.getKey(); |
81 if (key <= Integer.MAX_VALUE) { |
81 if (key <= Integer.MAX_VALUE) { |
82 objArray[(int)key] = entry.getValue(); |
82 objArray[(int)key] = entry.getValue(); |
102 newSparseMap.put(Long.valueOf(newIndex), entry.getValue()); |
102 newSparseMap.put(Long.valueOf(newIndex), entry.getValue()); |
103 } |
103 } |
104 } |
104 } |
105 |
105 |
106 sparseMap = newSparseMap; |
106 sparseMap = newSparseMap; |
107 setLength(Math.max(length() - by, 0)); |
107 setLength(Math.max(length - by, 0)); |
108 } |
108 } |
109 |
109 |
110 @Override |
110 @Override |
111 public ArrayData shiftRight(final int by) { |
111 public ArrayData shiftRight(final int by) { |
112 final TreeMap<Long, Object> newSparseMap = new TreeMap<>(); |
112 final TreeMap<Long, Object> newSparseMap = new TreeMap<>(); |
113 if (underlying.length() + by > maxDenseLength) { |
113 if (underlying.length + by > maxDenseLength) { |
114 for (long i = maxDenseLength - by; i < underlying.length(); i++) { |
114 for (long i = maxDenseLength - by; i < underlying.length; i++) { |
115 if (underlying.has((int) i)) { |
115 if (underlying.has((int) i)) { |
116 newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i)); |
116 newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i)); |
117 } |
117 } |
118 } |
118 } |
119 underlying = underlying.shrink((int) (maxDenseLength - by)); |
119 underlying = underlying.shrink((int) (maxDenseLength - by)); |
125 final long newIndex = entry.getKey().longValue() + by; |
125 final long newIndex = entry.getKey().longValue() + by; |
126 newSparseMap.put(Long.valueOf(newIndex), entry.getValue()); |
126 newSparseMap.put(Long.valueOf(newIndex), entry.getValue()); |
127 } |
127 } |
128 |
128 |
129 sparseMap = newSparseMap; |
129 sparseMap = newSparseMap; |
130 setLength(length() + by); |
130 setLength(length + by); |
131 |
131 |
132 return this; |
132 return this; |
133 } |
133 } |
134 |
134 |
135 @Override |
135 @Override |
136 public ArrayData ensure(final long safeIndex) { |
136 public ArrayData ensure(final long safeIndex) { |
137 if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) { |
137 if (safeIndex < maxDenseLength && underlying.length <= safeIndex) { |
138 underlying = underlying.ensure(safeIndex); |
138 underlying = underlying.ensure(safeIndex); |
139 } |
139 } |
140 setLength(Math.max(safeIndex + 1, length())); |
140 setLength(Math.max(safeIndex + 1, length)); |
141 return this; |
141 return this; |
142 } |
142 } |
143 |
143 |
144 @Override |
144 @Override |
145 public ArrayData shrink(final long newLength) { |
145 public ArrayData shrink(final long newLength) { |
146 if (newLength < underlying.length()) { |
146 if (newLength < underlying.length) { |
147 underlying = underlying.shrink(newLength); |
147 underlying = underlying.shrink(newLength); |
148 underlying.setLength(newLength); |
148 underlying.setLength(newLength); |
149 sparseMap.clear(); |
149 sparseMap.clear(); |
150 setLength(newLength); |
150 setLength(newLength); |
151 } |
151 } |
158 @Override |
158 @Override |
159 public ArrayData set(final int index, final Object value, final boolean strict) { |
159 public ArrayData set(final int index, final Object value, final boolean strict) { |
160 if (index >= 0 && index < maxDenseLength) { |
160 if (index >= 0 && index < maxDenseLength) { |
161 ensure(index); |
161 ensure(index); |
162 underlying = underlying.set(index, value, strict); |
162 underlying = underlying.set(index, value, strict); |
163 setLength(Math.max(underlying.length(), length())); |
163 setLength(Math.max(underlying.length, length)); |
164 } else { |
164 } else { |
165 final Long longIndex = indexToKey(index); |
165 final Long longIndex = indexToKey(index); |
166 sparseMap.put(longIndex, value); |
166 sparseMap.put(longIndex, value); |
167 setLength(Math.max(longIndex + 1, length())); |
167 setLength(Math.max(longIndex + 1, length)); |
168 } |
168 } |
169 |
169 |
170 return this; |
170 return this; |
171 } |
171 } |
172 |
172 |
173 @Override |
173 @Override |
174 public ArrayData set(final int index, final int value, final boolean strict) { |
174 public ArrayData set(final int index, final int value, final boolean strict) { |
175 if (index >= 0 && index < maxDenseLength) { |
175 if (index >= 0 && index < maxDenseLength) { |
176 ensure(index); |
176 ensure(index); |
177 underlying = underlying.set(index, value, strict); |
177 underlying = underlying.set(index, value, strict); |
178 setLength(Math.max(underlying.length(), length())); |
178 setLength(Math.max(underlying.length, length)); |
179 } else { |
179 } else { |
180 final Long longIndex = indexToKey(index); |
180 final Long longIndex = indexToKey(index); |
181 sparseMap.put(longIndex, value); |
181 sparseMap.put(longIndex, value); |
182 setLength(Math.max(longIndex + 1, length())); |
182 setLength(Math.max(longIndex + 1, length)); |
183 } |
183 } |
184 return this; |
184 return this; |
185 } |
185 } |
186 |
186 |
187 @Override |
187 @Override |
188 public ArrayData set(final int index, final long value, final boolean strict) { |
188 public ArrayData set(final int index, final long value, final boolean strict) { |
189 if (index >= 0 && index < maxDenseLength) { |
189 if (index >= 0 && index < maxDenseLength) { |
190 ensure(index); |
190 ensure(index); |
191 underlying = underlying.set(index, value, strict); |
191 underlying = underlying.set(index, value, strict); |
192 setLength(Math.max(underlying.length(), length())); |
192 setLength(Math.max(underlying.length, length)); |
193 } else { |
193 } else { |
194 final Long longIndex = indexToKey(index); |
194 final Long longIndex = indexToKey(index); |
195 sparseMap.put(longIndex, value); |
195 sparseMap.put(longIndex, value); |
196 setLength(Math.max(longIndex + 1, length())); |
196 setLength(Math.max(longIndex + 1, length)); |
197 } |
197 } |
198 return this; |
198 return this; |
199 } |
199 } |
200 |
200 |
201 @Override |
201 @Override |
202 public ArrayData set(final int index, final double value, final boolean strict) { |
202 public ArrayData set(final int index, final double value, final boolean strict) { |
203 if (index >= 0 && index < maxDenseLength) { |
203 if (index >= 0 && index < maxDenseLength) { |
204 ensure(index); |
204 ensure(index); |
205 underlying = underlying.set(index, value, strict); |
205 underlying = underlying.set(index, value, strict); |
206 setLength(Math.max(underlying.length(), length())); |
206 setLength(Math.max(underlying.length, length)); |
207 } else { |
207 } else { |
208 final Long longIndex = indexToKey(index); |
208 final Long longIndex = indexToKey(index); |
209 sparseMap.put(longIndex, value); |
209 sparseMap.put(longIndex, value); |
210 setLength(Math.max(longIndex + 1, length())); |
210 setLength(Math.max(longIndex + 1, length)); |
211 } |
211 } |
212 return this; |
212 return this; |
213 } |
213 } |
214 |
214 |
215 @Override |
215 @Override |
292 } |
292 } |
293 |
293 |
294 @Override |
294 @Override |
295 public boolean has(final int index) { |
295 public boolean has(final int index) { |
296 if (index >= 0 && index < maxDenseLength) { |
296 if (index >= 0 && index < maxDenseLength) { |
297 return index < underlying.length() && underlying.has(index); |
297 return index < underlying.length && underlying.has(index); |
298 } |
298 } |
299 |
299 |
300 return sparseMap.containsKey(indexToKey(index)); |
300 return sparseMap.containsKey(indexToKey(index)); |
301 } |
301 } |
302 |
302 |
303 @Override |
303 @Override |
304 public ArrayData delete(final int index) { |
304 public ArrayData delete(final int index) { |
305 if (index >= 0 && index < maxDenseLength) { |
305 if (index >= 0 && index < maxDenseLength) { |
306 if (index < underlying.length()) { |
306 if (index < underlying.length) { |
307 underlying = underlying.delete(index); |
307 underlying = underlying.delete(index); |
308 } |
308 } |
309 } else { |
309 } else { |
310 sparseMap.remove(indexToKey(index)); |
310 sparseMap.remove(indexToKey(index)); |
311 } |
311 } |
334 return this; |
334 return this; |
335 } |
335 } |
336 |
336 |
337 @Override |
337 @Override |
338 public Object pop() { |
338 public Object pop() { |
339 if (length() == 0) { |
339 if (length == 0) { |
340 return ScriptRuntime.UNDEFINED; |
340 return ScriptRuntime.UNDEFINED; |
341 } |
341 } |
342 if (length() == underlying.length()) { |
342 if (length == underlying.length) { |
343 final Object result = underlying.pop(); |
343 final Object result = underlying.pop(); |
344 setLength(underlying.length()); |
344 setLength(underlying.length); |
345 return result; |
345 return result; |
346 } |
346 } |
347 setLength(length() - 1); |
347 setLength(length - 1); |
348 final Long key = Long.valueOf(length()); |
348 final Long key = Long.valueOf(length); |
349 return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED; |
349 return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED; |
350 } |
350 } |
351 |
351 |
352 @Override |
352 @Override |
353 public ArrayData slice(final long from, final long to) { |
353 public ArrayData slice(final long from, final long to) { |
354 assert to <= length(); |
354 assert to <= length; |
355 final long start = from < 0 ? (from + length()) : from; |
355 final long start = from < 0 ? (from + length) : from; |
356 final long newLength = to - start; |
356 final long newLength = to - start; |
357 |
357 |
358 if (start >= 0 && to <= maxDenseLength) { |
358 if (start >= 0 && to <= maxDenseLength) { |
359 if (newLength <= underlying.length()) { |
359 if (newLength <= underlying.length) { |
360 return underlying.slice(from, to); |
360 return underlying.slice(from, to); |
361 } |
361 } |
362 return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length(), newLength); |
362 return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length, newLength); |
363 } |
363 } |
364 |
364 |
365 ArrayData sliced = EMPTY_ARRAY; |
365 ArrayData sliced = EMPTY_ARRAY; |
366 sliced = sliced.ensure(newLength - 1); |
366 sliced = sliced.ensure(newLength - 1); |
367 for (long i = start; i < to; i = nextIndex(i)) { |
367 for (long i = start; i < to; i = nextIndex(i)) { |
368 if (has((int)i)) { |
368 if (has((int)i)) { |
369 sliced = sliced.set((int)(i - start), getObject((int)i), false); |
369 sliced = sliced.set((int)(i - start), getObject((int)i), false); |
370 } |
370 } |
371 } |
371 } |
372 assert sliced.length() == newLength; |
372 assert sliced.length == newLength; |
373 return sliced; |
373 return sliced; |
374 } |
374 } |
375 |
375 |
376 @Override |
376 @Override |
377 public long nextIndex(final long index) { |
377 public long nextIndex(final long index) { |
378 if (index < underlying.length() - 1) { |
378 if (index < underlying.length - 1) { |
379 return underlying.nextIndex(index); |
379 return underlying.nextIndex(index); |
380 } |
380 } |
381 |
381 |
382 final Long nextKey = sparseMap.higherKey(index); |
382 final Long nextKey = sparseMap.higherKey(index); |
383 if (nextKey != null) { |
383 if (nextKey != null) { |
384 return nextKey; |
384 return nextKey; |
385 } |
385 } |
386 return length(); |
386 return length; |
387 } |
387 } |
388 } |
388 } |