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 package libcore.io; 19 20 import java.io.FileDescriptor; 21 import java.io.IOException; 22 import java.nio.ByteBuffer; 23 import java.nio.ByteOrder; 24 25 /** 26 * Unsafe access to memory. 27 */ 28 public final class Memory { 29 private Memory() { } 30 31 /** 32 * Used to optimize nio heap buffer bulk get operations. 'dst' must be a primitive array. 33 * 'dstOffset' is measured in units of 'sizeofElements' bytes. 34 */ 35 public static native void unsafeBulkGet(Object dst, int dstOffset, int byteCount, 36 byte[] src, int srcOffset, int sizeofElements, boolean swap); 37 38 /** 39 * Used to optimize nio heap buffer bulk put operations. 'src' must be a primitive array. 40 * 'srcOffset' is measured in units of 'sizeofElements' bytes. 41 */ 42 public static native void unsafeBulkPut(byte[] dst, int dstOffset, int byteCount, 43 Object src, int srcOffset, int sizeofElements, boolean swap); 44 45 public static int peekInt(byte[] src, int offset, ByteOrder order) { 46 if (order == ByteOrder.BIG_ENDIAN) { 47 return (((src[offset++] & 0xff) << 24) | 48 ((src[offset++] & 0xff) << 16) | 49 ((src[offset++] & 0xff) << 8) | 50 ((src[offset ] & 0xff) << 0)); 51 } else { 52 return (((src[offset++] & 0xff) << 0) | 53 ((src[offset++] & 0xff) << 8) | 54 ((src[offset++] & 0xff) << 16) | 55 ((src[offset ] & 0xff) << 24)); 56 } 57 } 58 59 public static long peekLong(byte[] src, int offset, ByteOrder order) { 60 if (order == ByteOrder.BIG_ENDIAN) { 61 int h = ((src[offset++] & 0xff) << 24) | 62 ((src[offset++] & 0xff) << 16) | 63 ((src[offset++] & 0xff) << 8) | 64 ((src[offset++] & 0xff) << 0); 65 int l = ((src[offset++] & 0xff) << 24) | 66 ((src[offset++] & 0xff) << 16) | 67 ((src[offset++] & 0xff) << 8) | 68 ((src[offset ] & 0xff) << 0); 69 return (((long) h) << 32L) | ((long) l) & 0xffffffffL; 70 } else { 71 int l = ((src[offset++] & 0xff) << 0) | 72 ((src[offset++] & 0xff) << 8) | 73 ((src[offset++] & 0xff) << 16) | 74 ((src[offset++] & 0xff) << 24); 75 int h = ((src[offset++] & 0xff) << 0) | 76 ((src[offset++] & 0xff) << 8) | 77 ((src[offset++] & 0xff) << 16) | 78 ((src[offset ] & 0xff) << 24); 79 return (((long) h) << 32L) | ((long) l) & 0xffffffffL; 80 } 81 } 82 83 public static short peekShort(byte[] src, int offset, ByteOrder order) { 84 if (order == ByteOrder.BIG_ENDIAN) { 85 return (short) ((src[offset] << 8) | (src[offset + 1] & 0xff)); 86 } else { 87 return (short) ((src[offset + 1] << 8) | (src[offset] & 0xff)); 88 } 89 } 90 91 public static void pokeInt(byte[] dst, int offset, int value, ByteOrder order) { 92 if (order == ByteOrder.BIG_ENDIAN) { 93 dst[offset++] = (byte) ((value >> 24) & 0xff); 94 dst[offset++] = (byte) ((value >> 16) & 0xff); 95 dst[offset++] = (byte) ((value >> 8) & 0xff); 96 dst[offset ] = (byte) ((value >> 0) & 0xff); 97 } else { 98 dst[offset++] = (byte) ((value >> 0) & 0xff); 99 dst[offset++] = (byte) ((value >> 8) & 0xff); 100 dst[offset++] = (byte) ((value >> 16) & 0xff); 101 dst[offset ] = (byte) ((value >> 24) & 0xff); 102 } 103 } 104 105 public static void pokeLong(byte[] dst, int offset, long value, ByteOrder order) { 106 if (order == ByteOrder.BIG_ENDIAN) { 107 int i = (int) (value >> 32); 108 dst[offset++] = (byte) ((i >> 24) & 0xff); 109 dst[offset++] = (byte) ((i >> 16) & 0xff); 110 dst[offset++] = (byte) ((i >> 8) & 0xff); 111 dst[offset++] = (byte) ((i >> 0) & 0xff); 112 i = (int) value; 113 dst[offset++] = (byte) ((i >> 24) & 0xff); 114 dst[offset++] = (byte) ((i >> 16) & 0xff); 115 dst[offset++] = (byte) ((i >> 8) & 0xff); 116 dst[offset ] = (byte) ((i >> 0) & 0xff); 117 } else { 118 int i = (int) value; 119 dst[offset++] = (byte) ((i >> 0) & 0xff); 120 dst[offset++] = (byte) ((i >> 8) & 0xff); 121 dst[offset++] = (byte) ((i >> 16) & 0xff); 122 dst[offset++] = (byte) ((i >> 24) & 0xff); 123 i = (int) (value >> 32); 124 dst[offset++] = (byte) ((i >> 0) & 0xff); 125 dst[offset++] = (byte) ((i >> 8) & 0xff); 126 dst[offset++] = (byte) ((i >> 16) & 0xff); 127 dst[offset ] = (byte) ((i >> 24) & 0xff); 128 } 129 } 130 131 public static void pokeShort(byte[] dst, int offset, short value, ByteOrder order) { 132 if (order == ByteOrder.BIG_ENDIAN) { 133 dst[offset++] = (byte) ((value >> 8) & 0xff); 134 dst[offset ] = (byte) ((value >> 0) & 0xff); 135 } else { 136 dst[offset++] = (byte) ((value >> 0) & 0xff); 137 dst[offset ] = (byte) ((value >> 8) & 0xff); 138 } 139 } 140 141 /** 142 * Copies 'byteCount' bytes from the source to the destination. The objects are either 143 * instances of DirectByteBuffer or byte[]. The offsets in the byte[] case must include 144 * the Buffer.arrayOffset if the array came from a Buffer.array call. We could make this 145 * private and provide the four type-safe variants, but then ByteBuffer.put(ByteBuffer) 146 * would need to work out which to call based on whether the source and destination buffers 147 * are direct or not. 148 * 149 * @hide make type-safe before making public? 150 */ 151 public static native void memmove(Object dstObject, int dstOffset, Object srcObject, int srcOffset, long byteCount); 152 153 public static native byte peekByte(long address); 154 155 public static int peekInt(long address, boolean swap) { 156 int result = peekIntNative(address); 157 if (swap) { 158 result = Integer.reverseBytes(result); 159 } 160 return result; 161 } 162 private static native int peekIntNative(long address); 163 164 public static long peekLong(long address, boolean swap) { 165 long result = peekLongNative(address); 166 if (swap) { 167 result = Long.reverseBytes(result); 168 } 169 return result; 170 } 171 private static native long peekLongNative(long address); 172 173 public static short peekShort(long address, boolean swap) { 174 short result = peekShortNative(address); 175 if (swap) { 176 result = Short.reverseBytes(result); 177 } 178 return result; 179 } 180 private static native short peekShortNative(long address); 181 182 public static native void peekByteArray(long address, byte[] dst, int dstOffset, int byteCount); 183 public static native void peekCharArray(long address, char[] dst, int dstOffset, int charCount, boolean swap); 184 public static native void peekDoubleArray(long address, double[] dst, int dstOffset, int doubleCount, boolean swap); 185 public static native void peekFloatArray(long address, float[] dst, int dstOffset, int floatCount, boolean swap); 186 public static native void peekIntArray(long address, int[] dst, int dstOffset, int intCount, boolean swap); 187 public static native void peekLongArray(long address, long[] dst, int dstOffset, int longCount, boolean swap); 188 public static native void peekShortArray(long address, short[] dst, int dstOffset, int shortCount, boolean swap); 189 190 public static native void pokeByte(long address, byte value); 191 192 public static void pokeInt(long address, int value, boolean swap) { 193 if (swap) { 194 value = Integer.reverseBytes(value); 195 } 196 pokeIntNative(address, value); 197 } 198 private static native void pokeIntNative(long address, int value); 199 200 public static void pokeLong(long address, long value, boolean swap) { 201 if (swap) { 202 value = Long.reverseBytes(value); 203 } 204 pokeLongNative(address, value); 205 } 206 private static native void pokeLongNative(long address, long value); 207 208 public static void pokeShort(long address, short value, boolean swap) { 209 if (swap) { 210 value = Short.reverseBytes(value); 211 } 212 pokeShortNative(address, value); 213 } 214 private static native void pokeShortNative(long address, short value); 215 216 public static native void pokeByteArray(long address, byte[] src, int offset, int count); 217 public static native void pokeCharArray(long address, char[] src, int offset, int count, boolean swap); 218 public static native void pokeDoubleArray(long address, double[] src, int offset, int count, boolean swap); 219 public static native void pokeFloatArray(long address, float[] src, int offset, int count, boolean swap); 220 public static native void pokeIntArray(long address, int[] src, int offset, int count, boolean swap); 221 public static native void pokeLongArray(long address, long[] src, int offset, int count, boolean swap); 222 public static native void pokeShortArray(long address, short[] src, int offset, int count, boolean swap); 223 } 224