19651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia/* 2ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * Copyright (C) 2011 The Libphonenumber Authors 39651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * 49651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * Licensed under the Apache License, Version 2.0 (the "License"); 59651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * you may not use this file except in compliance with the License. 69651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * You may obtain a copy of the License at 79651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * 89651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * http://www.apache.org/licenses/LICENSE-2.0 99651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * 109651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * Unless required by applicable law or agreed to in writing, software 119651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * distributed under the License is distributed on an "AS IS" BASIS, 129651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * See the License for the specific language governing permissions and 149651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * limitations under the License. 159651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia */ 169651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 17f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jiapackage com.android.i18n.phonenumbers.prefixmapper; 189651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 199651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jiaimport java.io.IOException; 209651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jiaimport java.io.ObjectInput; 219651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jiaimport java.io.ObjectOutput; 229651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jiaimport java.nio.ByteBuffer; 239651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jiaimport java.util.Arrays; 249651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jiaimport java.util.Map.Entry; 259651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jiaimport java.util.SortedMap; 269651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jiaimport java.util.SortedSet; 279651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jiaimport java.util.TreeSet; 289651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 299651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia/** 30f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia * Flyweight phone prefix map storage strategy that uses a table to store unique strings and shorts 31f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia * to store the prefix and description indexes when possible. It is particularly space-efficient 32f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia * when the provided phone prefix map contains a lot of redundant descriptions. 339651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * 349651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia * @author Philippe Liard 359651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia */ 36f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jiafinal class FlyweightMapStorage extends PhonePrefixMapStorageStrategy { 379651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Size of short and integer types in bytes. 38ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia private static final int SHORT_NUM_BYTES = Short.SIZE / 8; 39ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia private static final int INT_NUM_BYTES = Integer.SIZE / 8; 409651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 419651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // The number of bytes used to store a phone number prefix. 429651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia private int prefixSizeInBytes; 439651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // The number of bytes used to store a description index. It is computed from the size of the 449651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // description pool containing all the strings. 459651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia private int descIndexSizeInBytes; 469651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 479651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia private ByteBuffer phoneNumberPrefixes; 489651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia private ByteBuffer descriptionIndexes; 499651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 509651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Sorted string array of unique description strings. 519651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia private String[] descriptionPool; 529651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 539651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia @Override 549651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia public int getPrefix(int index) { 559651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia return readWordFromBuffer(phoneNumberPrefixes, prefixSizeInBytes, index); 569651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 579651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 58ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia /** 59ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * This implementation returns the same string (same identity) when called for multiple indexes 60ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * corresponding to prefixes that have the same description. 61ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia */ 629651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia @Override 639651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia public String getDescription(int index) { 64ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia int indexInDescriptionPool = 65ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia readWordFromBuffer(descriptionIndexes, descIndexSizeInBytes, index); 66ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia return descriptionPool[indexInDescriptionPool]; 679651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 689651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 699651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia @Override 70f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia public void readFromSortedMap(SortedMap<Integer, String> phonePrefixMap) { 719651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia SortedSet<String> descriptionsSet = new TreeSet<String>(); 72f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia numOfEntries = phonePrefixMap.size(); 73f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia prefixSizeInBytes = getOptimalNumberOfBytesForValue(phonePrefixMap.lastKey()); 749651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia phoneNumberPrefixes = ByteBuffer.allocate(numOfEntries * prefixSizeInBytes); 759651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 769651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Fill the phone number prefixes byte buffer, the set of possible lengths of prefixes and the 779651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // description set. 789651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia int index = 0; 79f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia for (Entry<Integer, String> entry : phonePrefixMap.entrySet()) { 809651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia int prefix = entry.getKey(); 81ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia storeWordInBuffer(phoneNumberPrefixes, prefixSizeInBytes, index, prefix); 82f7e0224b862054893f28d2736b3f6804d9935886Shaopeng Jia possibleLengths.add((int) Math.log10(prefix) + 1); 839651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia descriptionsSet.add(entry.getValue()); 84ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia ++index; 859651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 86f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia createDescriptionPool(descriptionsSet, phonePrefixMap); 87ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } 889651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 89ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia /** 90f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia * Creates the description pool from the provided set of string descriptions and phone prefix map. 91ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia */ 92ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia private void createDescriptionPool(SortedSet<String> descriptionsSet, 93f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia SortedMap<Integer, String> phonePrefixMap) { 949651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia descIndexSizeInBytes = getOptimalNumberOfBytesForValue(descriptionsSet.size() - 1); 959651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia descriptionIndexes = ByteBuffer.allocate(numOfEntries * descIndexSizeInBytes); 969651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia descriptionPool = new String[descriptionsSet.size()]; 979651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia descriptionsSet.toArray(descriptionPool); 989651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 999651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Map the phone number prefixes to the descriptions. 100ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia int index = 0; 1019651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia for (int i = 0; i < numOfEntries; i++) { 102f7e0224b862054893f28d2736b3f6804d9935886Shaopeng Jia int prefix = readWordFromBuffer(phoneNumberPrefixes, prefixSizeInBytes, i); 103f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia String description = phonePrefixMap.get(prefix); 104ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia int positionInDescriptionPool = Arrays.binarySearch(descriptionPool, description); 105ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia storeWordInBuffer(descriptionIndexes, descIndexSizeInBytes, index, positionInDescriptionPool); 106ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia ++index; 1079651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 1089651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 1099651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 1109651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia @Override 1119651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia public void readExternal(ObjectInput objectInput) throws IOException { 1129651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Read binary words sizes. 1139651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia prefixSizeInBytes = objectInput.readInt(); 1149651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia descIndexSizeInBytes = objectInput.readInt(); 115ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 1169651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Read possible lengths. 1179651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia int sizeOfLengths = objectInput.readInt(); 1189651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia possibleLengths.clear(); 1199651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia for (int i = 0; i < sizeOfLengths; i++) { 1209651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia possibleLengths.add(objectInput.readInt()); 1219651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 122ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 1239651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Read description pool size. 1249651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia int descriptionPoolSize = objectInput.readInt(); 1259651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Read description pool. 1269651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia if (descriptionPool == null || descriptionPool.length < descriptionPoolSize) { 1279651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia descriptionPool = new String[descriptionPoolSize]; 1289651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 1299651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia for (int i = 0; i < descriptionPoolSize; i++) { 1309651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia String description = objectInput.readUTF(); 1319651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia descriptionPool[i] = description; 1329651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 133ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia readEntries(objectInput); 134ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } 135ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 136ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia /** 137f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia * Reads the phone prefix entries from the provided input stream and stores them to the internal 138f9768eb3c8f303725fb4f899598481cbc4fb76a3Shaopeng Jia * byte buffers. 139ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia */ 140ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia private void readEntries(ObjectInput objectInput) throws IOException { 1419651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia numOfEntries = objectInput.readInt(); 1429651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia if (phoneNumberPrefixes == null || phoneNumberPrefixes.capacity() < numOfEntries) { 143ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia phoneNumberPrefixes = ByteBuffer.allocate(numOfEntries * prefixSizeInBytes); 1449651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 1459651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia if (descriptionIndexes == null || descriptionIndexes.capacity() < numOfEntries) { 1469651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia descriptionIndexes = ByteBuffer.allocate(numOfEntries * descIndexSizeInBytes); 1479651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 1489651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia for (int i = 0; i < numOfEntries; i++) { 1499651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia readExternalWord(objectInput, prefixSizeInBytes, phoneNumberPrefixes, i); 1509651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia readExternalWord(objectInput, descIndexSizeInBytes, descriptionIndexes, i); 1519651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 1529651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 1539651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia 1549651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia @Override 1559651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia public void writeExternal(ObjectOutput objectOutput) throws IOException { 1569651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Write binary words sizes. 1579651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia objectOutput.writeInt(prefixSizeInBytes); 1589651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia objectOutput.writeInt(descIndexSizeInBytes); 159ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 1609651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Write possible lengths. 1619651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia int sizeOfLengths = possibleLengths.size(); 1629651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia objectOutput.writeInt(sizeOfLengths); 1639651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia for (Integer length : possibleLengths) { 1649651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia objectOutput.writeInt(length); 1659651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 166ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 1679651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Write description pool size. 1689651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia objectOutput.writeInt(descriptionPool.length); 1699651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Write description pool. 1709651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia for (String description : descriptionPool) { 1719651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia objectOutput.writeUTF(description); 1729651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 173ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 1749651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia // Write entries. 1759651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia objectOutput.writeInt(numOfEntries); 1769651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia for (int i = 0; i < numOfEntries; i++) { 1779651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia writeExternalWord(objectOutput, prefixSizeInBytes, phoneNumberPrefixes, i); 1789651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia writeExternalWord(objectOutput, descIndexSizeInBytes, descriptionIndexes, i); 1799651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 1809651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia } 181ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 182ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia /** 183ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * Gets the minimum number of bytes that can be used to store the provided {@code value}. 184ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia */ 185ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia private static int getOptimalNumberOfBytesForValue(int value) { 186ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia return value <= Short.MAX_VALUE ? SHORT_NUM_BYTES : INT_NUM_BYTES; 187ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } 188ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 189ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia /** 190ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * Stores a value which is read from the provided {@code objectInput} to the provided byte {@code 191ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * buffer} at the specified {@code index}. 192ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * 193ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param objectInput the object input stream from which the value is read 194ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param wordSize the number of bytes used to store the value read from the stream 195ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param outputBuffer the byte buffer to which the value is stored 196ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param index the index where the value is stored in the buffer 197ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @throws IOException if an error occurred reading from the object input stream 198ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia */ 199ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia private static void readExternalWord(ObjectInput objectInput, int wordSize, 200ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia ByteBuffer outputBuffer, int index) throws IOException { 201ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia int wordIndex = index * wordSize; 202ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia if (wordSize == SHORT_NUM_BYTES) { 203ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia outputBuffer.putShort(wordIndex, objectInput.readShort()); 204ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } else { 205ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia outputBuffer.putInt(wordIndex, objectInput.readInt()); 206ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } 207ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } 208ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 209ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia /** 210ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * Writes the value read from the provided byte {@code buffer} at the specified {@code index} to 211ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * the provided {@code objectOutput}. 212ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * 213ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param objectOutput the object output stream to which the value is written 214ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param wordSize the number of bytes used to store the value 215ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param inputBuffer the byte buffer from which the value is read 216ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param index the index of the value in the the byte buffer 217ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @throws IOException if an error occurred writing to the provided object output stream 218ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia */ 219ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia private static void writeExternalWord(ObjectOutput objectOutput, int wordSize, 220ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia ByteBuffer inputBuffer, int index) throws IOException { 221ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia int wordIndex = index * wordSize; 222ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia if (wordSize == SHORT_NUM_BYTES) { 223ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia objectOutput.writeShort(inputBuffer.getShort(wordIndex)); 224ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } else { 225ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia objectOutput.writeInt(inputBuffer.getInt(wordIndex)); 226ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } 227ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } 228ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 229ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia /** 230ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * Reads the {@code value} at the specified {@code index} from the provided byte {@code buffer}. 231ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * Note that only integer and short sizes are supported. 232ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * 233ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param buffer the byte buffer from which the value is read 234ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param wordSize the number of bytes used to store the value 235ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param index the index where the value is read from 236ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * 237ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @return the value read from the buffer 238ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia */ 239ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia private static int readWordFromBuffer(ByteBuffer buffer, int wordSize, int index) { 240ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia int wordIndex = index * wordSize; 241ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia return wordSize == SHORT_NUM_BYTES ? buffer.getShort(wordIndex) : buffer.getInt(wordIndex); 242ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } 243ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia 244ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia /** 245ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * Stores the provided {@code value} to the provided byte {@code buffer} at the specified {@code 246ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * index} using the provided {@code wordSize} in bytes. Note that only integer and short sizes are 247ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * supported. 248ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * 249ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param buffer the byte buffer to which the value is stored 250ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param wordSize the number of bytes used to store the provided value 251ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param index the index to which the value is stored 252ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * @param value the value that is stored assuming it does not require more than the specified 253ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * number of bytes. 254ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia */ 255ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia private static void storeWordInBuffer(ByteBuffer buffer, int wordSize, int index, int value) { 256ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia int wordIndex = index * wordSize; 257ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia if (wordSize == SHORT_NUM_BYTES) { 258ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia buffer.putShort(wordIndex, (short) value); 259ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } else { 260ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia buffer.putInt(wordIndex, value); 261ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } 262ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia } 2639651f4d6f2740017c0c4ea9c1c340af6f644d609Shaopeng Jia} 264