1 /*
2  * Copyright (C) 2015 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 
17 package android.support.v7.util;
18 
19 import android.util.SparseArray;
20 
21 import java.lang.reflect.Array;
22 
23 /**
24  * A sparse collection of tiles sorted for efficient access.
25  */
26 class TileList<T> {
27 
28     final int mTileSize;
29 
30     // Keyed by start position.
31     private final SparseArray<Tile<T>> mTiles = new SparseArray<Tile<T>>(10);
32 
33     Tile<T> mLastAccessedTile;
34 
TileList(int tileSize)35     public TileList(int tileSize) {
36         mTileSize = tileSize;
37     }
38 
getItemAt(int pos)39     public T getItemAt(int pos) {
40         if (mLastAccessedTile == null || !mLastAccessedTile.containsPosition(pos)) {
41             final int startPosition = pos - (pos % mTileSize);
42             final int index = mTiles.indexOfKey(startPosition);
43             if (index < 0) {
44                 return null;
45             }
46             mLastAccessedTile = mTiles.valueAt(index);
47         }
48         return mLastAccessedTile.getByPosition(pos);
49     }
50 
size()51     public int size() {
52         return mTiles.size();
53     }
54 
clear()55     public void clear() {
56         mTiles.clear();
57     }
58 
getAtIndex(int index)59     public Tile<T> getAtIndex(int index) {
60         return mTiles.valueAt(index);
61     }
62 
addOrReplace(Tile<T> newTile)63     public Tile<T> addOrReplace(Tile<T> newTile) {
64         final int index = mTiles.indexOfKey(newTile.mStartPosition);
65         if (index < 0) {
66             mTiles.put(newTile.mStartPosition, newTile);
67             return null;
68         }
69         Tile<T> oldTile = mTiles.valueAt(index);
70         mTiles.setValueAt(index, newTile);
71         if (mLastAccessedTile == oldTile) {
72             mLastAccessedTile = newTile;
73         }
74         return oldTile;
75     }
76 
removeAtPos(int startPosition)77     public Tile<T> removeAtPos(int startPosition) {
78         Tile<T> tile = mTiles.get(startPosition);
79         if (mLastAccessedTile == tile) {
80             mLastAccessedTile = null;
81         }
82         mTiles.delete(startPosition);
83         return tile;
84     }
85 
86     public static class Tile<T> {
87         public final T[] mItems;
88         public int mStartPosition;
89         public int mItemCount;
90         Tile<T> mNext;  // Used only for pooling recycled tiles.
91 
Tile(Class<T> klass, int size)92         public Tile(Class<T> klass, int size) {
93             //noinspection unchecked
94             mItems = (T[]) Array.newInstance(klass, size);
95         }
96 
containsPosition(int pos)97         boolean containsPosition(int pos) {
98             return mStartPosition <= pos && pos < mStartPosition + mItemCount;
99         }
100 
getByPosition(int pos)101         T getByPosition(int pos) {
102             return mItems[pos - mStartPosition];
103         }
104     }
105 }
106