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;
20
21class PackedObjectVector<E>
22{
23    private int mColumns;
24    private int mRows;
25
26    private int mRowGapStart;
27    private int mRowGapLength;
28
29    private Object[] mValues;
30
31    public
32    PackedObjectVector(int columns)
33    {
34        mColumns = columns;
35        mRows = ArrayUtils.idealIntArraySize(0) / mColumns;
36
37        mRowGapStart = 0;
38        mRowGapLength = mRows;
39
40        mValues = new Object[mRows * mColumns];
41    }
42
43    public E
44    getValue(int row, int column)
45    {
46        if (row >= mRowGapStart)
47            row += mRowGapLength;
48
49        Object value = mValues[row * mColumns + column];
50
51        return (E) value;
52    }
53
54    public void
55    setValue(int row, int column, E value)
56    {
57        if (row >= mRowGapStart)
58            row += mRowGapLength;
59
60        mValues[row * mColumns + column] = value;
61    }
62
63    public void
64    insertAt(int row, E[] values)
65    {
66        moveRowGapTo(row);
67
68        if (mRowGapLength == 0)
69            growBuffer();
70
71        mRowGapStart++;
72        mRowGapLength--;
73
74        if (values == null)
75            for (int i = 0; i < mColumns; i++)
76                setValue(row, i, null);
77        else
78            for (int i = 0; i < mColumns; i++)
79                setValue(row, i, values[i]);
80    }
81
82    public void
83    deleteAt(int row, int count)
84    {
85        moveRowGapTo(row + count);
86
87        mRowGapStart -= count;
88        mRowGapLength += count;
89
90        if (mRowGapLength > size() * 2)
91        {
92            // dump();
93            // growBuffer();
94        }
95    }
96
97    public int
98    size()
99    {
100        return mRows - mRowGapLength;
101    }
102
103    public int
104    width()
105    {
106        return mColumns;
107    }
108
109    private void
110    growBuffer()
111    {
112        int newsize = size() + 1;
113        newsize = ArrayUtils.idealIntArraySize(newsize * mColumns) / mColumns;
114        Object[] newvalues = new Object[newsize * mColumns];
115
116        int after = mRows - (mRowGapStart + mRowGapLength);
117
118        System.arraycopy(mValues, 0, newvalues, 0, mColumns * mRowGapStart);
119        System.arraycopy(mValues, (mRows - after) * mColumns, newvalues, (newsize - after) * mColumns, after * mColumns);
120
121        mRowGapLength += newsize - mRows;
122        mRows = newsize;
123        mValues = newvalues;
124    }
125
126    private void
127    moveRowGapTo(int where)
128    {
129        if (where == mRowGapStart)
130            return;
131
132        if (where > mRowGapStart)
133        {
134            int moving = where + mRowGapLength - (mRowGapStart + mRowGapLength);
135
136            for (int i = mRowGapStart + mRowGapLength; i < mRowGapStart + mRowGapLength + moving; i++)
137            {
138                int destrow = i - (mRowGapStart + mRowGapLength) + mRowGapStart;
139
140                for (int j = 0; j < mColumns; j++)
141                {
142                    Object val = mValues[i * mColumns + j];
143
144                    mValues[destrow * mColumns + j] = val;
145                }
146            }
147        }
148        else /* where < mRowGapStart */
149        {
150            int moving = mRowGapStart - where;
151
152            for (int i = where + moving - 1; i >= where; i--)
153            {
154                int destrow = i - where + mRowGapStart + mRowGapLength - moving;
155
156                for (int j = 0; j < mColumns; j++)
157                {
158                    Object val = mValues[i * mColumns + j];
159
160                    mValues[destrow * mColumns + j] = val;
161                }
162            }
163        }
164
165        mRowGapStart = where;
166    }
167
168    public void // XXX
169    dump()
170    {
171        for (int i = 0; i < mRows; i++)
172        {
173            for (int j = 0; j < mColumns; j++)
174            {
175                Object val = mValues[i * mColumns + j];
176
177                if (i < mRowGapStart || i >= mRowGapStart + mRowGapLength)
178                    System.out.print(val + " ");
179                else
180                    System.out.print("(" + val + ") ");
181            }
182
183            System.out.print(" << \n");
184        }
185
186        System.out.print("-----\n\n");
187    }
188}
189