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