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