| /* |
| * Copyright 2000-2009 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.openapi.editor.ex.util; |
| |
| import org.jetbrains.annotations.NotNull; |
| |
| /** |
| * Expands {@link SegmentArray} contract in providing ability to attach additional <code>'short'</code> variable to target segment, |
| * i.e. holds mappings like {@code 'index <-> (data, (start; end))'}. |
| * <p/> |
| * Not thread-safe. |
| */ |
| public class SegmentArrayWithData extends SegmentArray { |
| private short[] myData; |
| |
| public SegmentArrayWithData() { |
| myData = new short[INITIAL_SIZE]; |
| } |
| |
| public void setElementAt(int i, int startOffset, int endOffset, int data) { |
| if (data < 0 && data > Short.MAX_VALUE) throw new IndexOutOfBoundsException("data out of short range" + data); |
| super.setElementAt(i, startOffset, endOffset); |
| myData = reallocateArray(myData, i+1); |
| myData[i] = (short)data; |
| } |
| |
| @Override |
| public void remove(int startIndex, int endIndex) { |
| myData = remove(myData, startIndex, endIndex); |
| super.remove(startIndex, endIndex); |
| } |
| |
| public void replace(int startIndex, int endIndex, @NotNull SegmentArrayWithData newData) { |
| int oldLen = endIndex - startIndex; |
| int newLen = newData.getSegmentCount(); |
| |
| int delta = newLen - oldLen; |
| if (delta < 0) { |
| remove(endIndex + delta, endIndex); |
| } |
| else if (delta > 0) { |
| SegmentArrayWithData deltaData = new SegmentArrayWithData(); |
| for (int i = oldLen; i < newLen; i++) { |
| deltaData.setElementAt(i - oldLen, newData.getSegmentStart(i), newData.getSegmentEnd(i), newData.getSegmentData(i)); |
| } |
| insert(deltaData, startIndex + oldLen); |
| } |
| |
| int common = Math.min(newLen, oldLen); |
| replace(startIndex, newData, common); |
| } |
| |
| |
| protected void replace(int startOffset, @NotNull SegmentArrayWithData data, int len) { |
| System.arraycopy(data.myData, 0, myData, startOffset, len); |
| super.replace(startOffset, data, len); |
| } |
| |
| public void insert(@NotNull SegmentArrayWithData segmentArray, int startIndex) { |
| myData = insert(myData, segmentArray.myData, startIndex, segmentArray.getSegmentCount()); |
| super.insert(segmentArray, startIndex); |
| } |
| |
| @NotNull |
| private short[] insert(@NotNull short[] array, @NotNull short[] insertArray, int startIndex, int insertLength) { |
| short[] newArray = reallocateArray(array, mySegmentCount + insertLength); |
| if (startIndex < mySegmentCount) { |
| System.arraycopy(newArray, startIndex, newArray, startIndex + insertLength, mySegmentCount - startIndex); |
| } |
| System.arraycopy(insertArray, 0, newArray, startIndex, insertLength); |
| return newArray; |
| } |
| |
| @NotNull |
| private short[] remove(@NotNull short[] array, int startIndex, int endIndex) { |
| if (endIndex < mySegmentCount) { |
| System.arraycopy(array, endIndex, array, startIndex, mySegmentCount - endIndex); |
| } |
| return array; |
| } |
| |
| public short getSegmentData(int index) { |
| if(index < 0 || index >= mySegmentCount) { |
| throw new IndexOutOfBoundsException("Wrong index: " + index); |
| } |
| return myData[index]; |
| } |
| |
| public void setSegmentData(int index, int data) { |
| if(index < 0 || index >= mySegmentCount) throw new IndexOutOfBoundsException("Wrong index: " + index); |
| if (data < 0 && data > Short.MAX_VALUE) throw new IndexOutOfBoundsException("data out of short range" + data); |
| myData[index] = (short)data; |
| } |
| |
| @NotNull |
| private static short[] reallocateArray(@NotNull short[] array, int index) { |
| if (index < array.length) return array; |
| |
| short[] newArray = new short[calcCapacity(array.length, index)]; |
| System.arraycopy(array, 0, newArray, 0, array.length); |
| return newArray; |
| } |
| |
| } |
| |