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