1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.text;
18
19import com.android.internal.util.ArrayUtils;
20import com.android.internal.util.GrowingArrayUtils;
21
22import libcore.util.EmptyArray;
23
24class PackedObjectVector<E>
25{
26    private int mColumns;
27    private int mRows;
28
29    private int mRowGapStart;
30    private int mRowGapLength;
31
32    private Object[] mValues;
33
34    public
35    PackedObjectVector(int columns)
36    {
37        mColumns = columns;
38        mValues = EmptyArray.OBJECT;
39        mRows = 0;
40
41        mRowGapStart = 0;
42        mRowGapLength = mRows;
43    }
44
45    public E
46    getValue(int row, int column)
47    {
48        if (row >= mRowGapStart)
49            row += mRowGapLength;
50
51        Object value = mValues[row * mColumns + column];
52
53        return (E) value;
54    }
55
56    public void
57    setValue(int row, int column, E value)
58    {
59        if (row >= mRowGapStart)
60            row += mRowGapLength;
61
62        mValues[row * mColumns + column] = value;
63    }
64
65    public void
66    insertAt(int row, E[] values)
67    {
68        moveRowGapTo(row);
69
70        if (mRowGapLength == 0)
71            growBuffer();
72
73        mRowGapStart++;
74        mRowGapLength--;
75
76        if (values == null)
77            for (int i = 0; i < mColumns; i++)
78                setValue(row, i, null);
79        else
80            for (int i = 0; i < mColumns; i++)
81                setValue(row, i, values[i]);
82    }
83
84    public void
85    deleteAt(int row, int count)
86    {
87        moveRowGapTo(row + count);
88
89        mRowGapStart -= count;
90        mRowGapLength += count;
91
92        if (mRowGapLength > size() * 2)
93        {
94            // dump();
95            // growBuffer();
96        }
97    }
98
99    public int
100    size()
101    {
102        return mRows - mRowGapLength;
103    }
104
105    public int
106    width()
107    {
108        return mColumns;
109    }
110
111    private void
112    growBuffer()
113    {
114        Object[] newvalues = ArrayUtils.newUnpaddedObjectArray(
115                GrowingArrayUtils.growSize(size()) * mColumns);
116        int newsize = newvalues.length / mColumns;
117        int after = mRows - (mRowGapStart + mRowGapLength);
118
119        System.arraycopy(mValues, 0, newvalues, 0, mColumns * mRowGapStart);
120        System.arraycopy(mValues, (mRows - after) * mColumns, newvalues, (newsize - after) * mColumns, after * mColumns);
121
122        mRowGapLength += newsize - mRows;
123        mRows = newsize;
124        mValues = newvalues;
125    }
126
127    private void
128    moveRowGapTo(int where)
129    {
130        if (where == mRowGapStart)
131            return;
132
133        if (where > mRowGapStart)
134        {
135            int moving = where + mRowGapLength - (mRowGapStart + mRowGapLength);
136
137            for (int i = mRowGapStart + mRowGapLength; i < mRowGapStart + mRowGapLength + moving; i++)
138            {
139                int destrow = i - (mRowGapStart + mRowGapLength) + mRowGapStart;
140
141                for (int j = 0; j < mColumns; j++)
142                {
143                    Object val = mValues[i * mColumns + j];
144
145                    mValues[destrow * mColumns + j] = val;
146                }
147            }
148        }
149        else /* where < mRowGapStart */
150        {
151            int moving = mRowGapStart - where;
152
153            for (int i = where + moving - 1; i >= where; i--)
154            {
155                int destrow = i - where + mRowGapStart + mRowGapLength - moving;
156
157                for (int j = 0; j < mColumns; j++)
158                {
159                    Object val = mValues[i * mColumns + j];
160
161                    mValues[destrow * mColumns + j] = val;
162                }
163            }
164        }
165
166        mRowGapStart = where;
167    }
168
169    public void // XXX
170    dump()
171    {
172        for (int i = 0; i < mRows; i++)
173        {
174            for (int j = 0; j < mColumns; j++)
175            {
176                Object val = mValues[i * mColumns + j];
177
178                if (i < mRowGapStart || i >= mRowGapStart + mRowGapLength)
179                    System.out.print(val + " ");
180                else
181                    System.out.print("(" + val + ") ");
182            }
183
184            System.out.print(" << \n");
185        }
186
187        System.out.print("-----\n\n");
188    }
189}
190