1 /* 2 * Copyright (C) 2010 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 libcore.io; 18 19 /** 20 * Iterates over big- or little-endian bytes on the native heap. 21 * See {@link MemoryMappedFile#bigEndianIterator} and {@link MemoryMappedFile#littleEndianIterator}. 22 * 23 * @hide 24 */ 25 public final class NioBufferIterator extends BufferIterator { 26 27 private final MemoryMappedFile file; 28 private final long address; 29 private final int length; 30 private final boolean swap; 31 32 private int position; 33 NioBufferIterator(MemoryMappedFile file, long address, int length, boolean swap)34 NioBufferIterator(MemoryMappedFile file, long address, int length, boolean swap) { 35 file.checkNotClosed(); 36 37 this.file = file; 38 this.address = address; 39 40 if (length < 0) { 41 throw new IllegalArgumentException("length < 0"); 42 } 43 final long MAX_VALID_ADDRESS = -1; 44 if (Long.compareUnsigned(address, MAX_VALID_ADDRESS - length) > 0) { 45 throw new IllegalArgumentException( 46 "length " + length + " would overflow 64-bit address space"); 47 } 48 this.length = length; 49 50 this.swap = swap; 51 } 52 seek(int offset)53 public void seek(int offset) { 54 position = offset; 55 } 56 skip(int byteCount)57 public void skip(int byteCount) { 58 position += byteCount; 59 } 60 61 @Override pos()62 public int pos() { 63 return position; 64 } 65 readByteArray(byte[] dst, int dstOffset, int byteCount)66 public void readByteArray(byte[] dst, int dstOffset, int byteCount) { 67 checkDstBounds(dstOffset, dst.length, byteCount); 68 file.checkNotClosed(); 69 checkReadBounds(position, length, byteCount); 70 Memory.peekByteArray(address + position, dst, dstOffset, byteCount); 71 position += byteCount; 72 } 73 readByte()74 public byte readByte() { 75 file.checkNotClosed(); 76 checkReadBounds(position, length, 1); 77 byte result = Memory.peekByte(address + position); 78 ++position; 79 return result; 80 } 81 readInt()82 public int readInt() { 83 file.checkNotClosed(); 84 checkReadBounds(position, length, SizeOf.INT); 85 int result = Memory.peekInt(address + position, swap); 86 position += SizeOf.INT; 87 return result; 88 } 89 readIntArray(int[] dst, int dstOffset, int intCount)90 public void readIntArray(int[] dst, int dstOffset, int intCount) { 91 checkDstBounds(dstOffset, dst.length, intCount); 92 file.checkNotClosed(); 93 final int byteCount = SizeOf.INT * intCount; 94 checkReadBounds(position, length, byteCount); 95 Memory.peekIntArray(address + position, dst, dstOffset, intCount, swap); 96 position += byteCount; 97 } 98 readShort()99 public short readShort() { 100 file.checkNotClosed(); 101 checkReadBounds(position, length, SizeOf.SHORT); 102 short result = Memory.peekShort(address + position, swap); 103 position += SizeOf.SHORT; 104 return result; 105 } 106 checkReadBounds(int position, int length, int byteCount)107 private static void checkReadBounds(int position, int length, int byteCount) { 108 if (position < 0 || byteCount < 0) { 109 throw new IndexOutOfBoundsException( 110 "Invalid read args: position=" + position + ", byteCount=" + byteCount); 111 } 112 // Use of int here relies on length being an int <= Integer.MAX_VALUE. 113 final int finalReadPos = position + byteCount; 114 if (finalReadPos < 0 || finalReadPos > length) { 115 throw new IndexOutOfBoundsException( 116 "Read outside range: position=" + position + ", byteCount=" + byteCount 117 + ", length=" + length); 118 } 119 } 120 checkDstBounds(int dstOffset, int dstLength, int count)121 private static void checkDstBounds(int dstOffset, int dstLength, int count) { 122 if (dstOffset < 0 || count < 0) { 123 throw new IndexOutOfBoundsException( 124 "Invalid dst args: offset=" + dstLength + ", count=" + count); 125 } 126 // Use of int here relies on dstLength being an int <= Integer.MAX_VALUE, which it has to 127 // be because it's an array length. 128 final int targetPos = dstOffset + count; 129 if (targetPos < 0 || targetPos > dstLength) { 130 throw new IndexOutOfBoundsException( 131 "Write outside range: dst.length=" + dstLength + ", offset=" 132 + dstOffset + ", count=" + count); 133 } 134 } 135 } 136