1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /* $Id: IntegerKeyStore.java 1564017 2014-02-03 19:29:24Z vhennebert $ */
19 
20 package org.apache.fop.afp.fonts;
21 
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Map;
26 
27 /**
28  * A simple compact data structure to model a sparse array
29  */
30 class IntegerKeyStore<T> {
31 
32     private static final int RANGE_BIT_SIZE = 8;
33 
34     private static final int RANGE_SIZE = 1 << RANGE_BIT_SIZE;
35 
36     private final Map<Integer, ArrayList<T>> arrays = new HashMap<Integer, ArrayList<T>>();
37 
38     /**
39      *
40      * @param index a positive integer
41      * @param value value to store
42      */
put(Integer index, T value)43     public void put(Integer index, T value) {
44         if (index < 0) {
45             throw new IndexOutOfBoundsException();
46         }
47         int rangeKey = index >> RANGE_BIT_SIZE;
48         int rangeIndex = index % RANGE_SIZE;
49         ArrayList<T> range = arrays.get(rangeKey);
50         if (range == null) {
51             range = new ArrayList<T>(Collections.<T>nCopies(RANGE_SIZE, null));
52             arrays.put(rangeKey, range);
53         }
54         range.set(rangeIndex, value);
55     }
56 
57     /**
58      *
59      * @param index a positive integer
60      * @return value the value associated with the index or null
61      */
get(Integer index)62     public T get(Integer index) {
63         if (index < 0) {
64             throw new IndexOutOfBoundsException();
65         }
66         int rangeKey = index >> RANGE_BIT_SIZE;
67         int rangeIndex = index % RANGE_SIZE;
68         ArrayList<T> range = arrays.get(rangeKey);
69         return range == null ? null : range.get(rangeIndex);
70     }
71 }
72