| /*=============================================================================# |
| # Copyright (c) 2009, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.rj.data.impl; |
| |
| import java.io.IOException; |
| |
| import org.eclipse.statet.rj.data.RList; |
| import org.eclipse.statet.rj.data.RObject; |
| import org.eclipse.statet.rj.data.RStore; |
| |
| |
| public abstract class AbstractRObject implements RObject { |
| |
| |
| protected static final RObject[] EMPTY_ROBJECT_ARRAY= new RObject[0]; |
| protected static final RObject[][] EMPTY_ROBJECT_2dARRAY= new RObject[0][]; |
| |
| |
| protected static final long check2dArrayLength(final RObject[][] array, final int segmentLength) { |
| long length= 0; |
| if (array.length > 0) { |
| final int last= array.length - 1; |
| for (int i= 0; i < last; i++) { |
| if (array[i].length != segmentLength) { |
| throw new IllegalArgumentException("Unexpected list segment length (" + array[i].length + ", but " + segmentLength + " expected)"); |
| } |
| } |
| length= last * (long)segmentLength; |
| if (array[last].length > segmentLength) { |
| throw new IllegalArgumentException("Unexpected list segment length (" + array[last].length + ", but max " + segmentLength + " expected)"); |
| } |
| length+= array[last].length; |
| } |
| return length; |
| } |
| |
| protected static final RObject[][] new2dRObjectArray(final long length, final int segmentLength) { |
| if (length == 0) { |
| return EMPTY_ROBJECT_2dARRAY; |
| } |
| final RObject[][] array= new RObject[1 + (int)((length - 1) / segmentLength)][]; |
| final int last= array.length - 1; |
| for (int i= 0; i < last; i++) { |
| array[i]= new RObject[segmentLength]; |
| } |
| { final int restLength= (int)(length % segmentLength); |
| array[last]= new RObject[(restLength == 0) ? segmentLength : restLength]; |
| } |
| return array; |
| } |
| |
| |
| protected static final int checkShortLength(final long length) throws IOException { |
| if (length >= Integer.MAX_VALUE) { |
| throw new IOException("Long length (" + length + ") not supported by this implementation."); |
| } |
| return (int)length; |
| } |
| |
| |
| protected static final int getNewArraySize(final int length) { |
| if (length >= 0xfffffff) { |
| return Integer.MAX_VALUE; |
| } |
| return ((length+0x7) | 0xf) + 1; |
| } |
| |
| protected static final RObject[] ensureCapacity(final RObject[] currentValues, final int length) { |
| if (currentValues.length >= length) { |
| return currentValues; |
| } |
| return new RObject[getNewArraySize(length)]; |
| } |
| |
| protected static final RStore<?>[] ensureCapacity(final RStore<?>[] currentValues, final int length) { |
| if (currentValues.length >= length) { |
| return currentValues; |
| } |
| return new RStore[getNewArraySize(length)]; |
| } |
| |
| protected static final RObject[] prepareInsert(final RObject[] currentValues, final int currentLength, final int[] idxs) { |
| final RObject[] newValues= ensureCapacity(currentValues, currentLength+idxs.length); |
| int i= idxs.length-1; |
| System.arraycopy(currentValues, idxs[i], newValues, idxs[i]+i+1, currentLength-idxs[i]); |
| for (i--; i >= 0; i--) { |
| System.arraycopy(currentValues, idxs[i], newValues, idxs[i]+i+1, idxs[i+1]-idxs[i]); |
| } |
| if (currentValues != newValues) { |
| System.arraycopy(currentValues, 0, newValues, 0, idxs[0]); |
| } |
| return newValues; |
| } |
| |
| protected static final RStore<?>[] prepareInsert(final RStore<?>[] currentValues, final int currentLength, final int[] idxs) { |
| final RStore<?>[] newValues= ensureCapacity(currentValues, currentLength+idxs.length); |
| int i= idxs.length-1; |
| System.arraycopy(currentValues, idxs[i], newValues, idxs[i]+i+1, currentLength-idxs[i]); |
| for (i--; i >= 0; i--) { |
| System.arraycopy(currentValues, idxs[i], newValues, idxs[i]+i+1, idxs[i+1]-idxs[i]); |
| } |
| if (currentValues != newValues) { |
| System.arraycopy(currentValues, 0, newValues, 0, idxs[0]); |
| } |
| return newValues; |
| } |
| |
| protected static final RObject[] remove(final RObject[] currentValues, final int currentLength, final int[] idxs) { |
| final RObject[] newValues= ensureCapacity(currentValues, currentLength-idxs.length); |
| if (currentValues != newValues) { |
| System.arraycopy(currentValues, 0, newValues, 0, idxs[0]); |
| } |
| int i= 0; |
| for (; i < idxs.length-1; i++) { |
| System.arraycopy(currentValues, idxs[i]+1, newValues, idxs[i]-i, idxs[i+1]-idxs[i]); |
| } |
| System.arraycopy(currentValues, idxs[i]+1, newValues, idxs[i]-i, currentLength-idxs[i]-1); |
| return newValues; |
| } |
| |
| protected static final RStore<?>[] remove(final RStore<?>[] currentValues, final int currentLength, final int[] idxs) { |
| final RStore<?>[] newValues= ensureCapacity(currentValues, currentLength-idxs.length); |
| if (currentValues != newValues) { |
| System.arraycopy(currentValues, 0, newValues, 0, idxs[0]); |
| } |
| int i= 0; |
| for (; i < idxs.length-1; i++) { |
| System.arraycopy(currentValues, idxs[i]+1, newValues, idxs[i]-i, idxs[i+1]-idxs[i]); |
| } |
| System.arraycopy(currentValues, idxs[i]+1, newValues, idxs[i]-i, currentLength-idxs[i]-1); |
| return newValues; |
| } |
| |
| |
| private RList attributes; |
| |
| |
| protected void setAttributes(final RList attributes) { |
| this.attributes= attributes; |
| } |
| |
| @Override |
| public final RList getAttributes() { |
| return this.attributes; |
| } |
| |
| } |