1/*
2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26/*
27 */
28
29#include "jni.h"
30#include "jni_util.h"
31#include "jlong.h"
32#include <string.h>
33
34#include <nativehelper/JNIHelp.h>
35
36/*
37 * WARNING:
38 *
39 * Do not replace instances of:
40 *
41 *   if (length > MBYTE)
42 *     size = MBYTE;
43 *   else
44 *     size = length;
45 *
46 * with
47 *
48 *   size = (length > MBYTE ? MBYTE : length);
49 *
50 * This expression causes a c compiler assertion failure when compiling on
51 * 32-bit sparc.
52 */
53
54#define MBYTE 1048576
55
56#define GETCRITICAL(bytes, env, obj) { \
57    (bytes) = (*(env))->GetPrimitiveArrayCritical(env, obj, NULL); \
58    if ((bytes) == NULL) \
59        JNU_ThrowInternalError(env, "Unable to get array"); \
60}
61
62#define RELEASECRITICAL(bytes, env, obj, mode) { \
63    (*(env))->ReleasePrimitiveArrayCritical(env, obj, bytes, mode); \
64}
65
66#define SWAPSHORT(x) ((jshort)(((x) << 8) | (((x) >> 8) & 0xff)))
67#define SWAPINT(x)   ((jint)((SWAPSHORT((jshort)(x)) << 16) | \
68                            (SWAPSHORT((jshort)((x) >> 16)) & 0xffff)))
69#define SWAPLONG(x)  ((jlong)(((jlong)SWAPINT((jint)(x)) << 32) | \
70                              ((jlong)SWAPINT((jint)((x) >> 32)) & 0xffffffff)))
71
72#define NATIVE_METHOD(className, functionName, signature) \
73{ #functionName, signature, (void*)(Java_java_nio_ ## className ## _ ## functionName) }
74
75JNIEXPORT void JNICALL
76Java_java_nio_Bits_copyFromShortArray(JNIEnv *env, jobject this, jobject src,
77                                      jlong srcPos, jlong dstAddr, jlong length)
78{
79    jbyte *bytes;
80    size_t size;
81    jshort *srcShort, *dstShort, *endShort;
82    jshort tmpShort;
83
84    dstShort = (jshort *)jlong_to_ptr(dstAddr);
85
86    while (length > 0) {
87        /* do not change this if-else statement, see WARNING above */
88        if (length > MBYTE)
89            size = MBYTE;
90        else
91            size = (size_t)length;
92
93        GETCRITICAL(bytes, env, src);
94
95        srcShort = (jshort *)(bytes + srcPos);
96        endShort = srcShort + (size / sizeof(jshort));
97        while (srcShort < endShort) {
98          tmpShort = *srcShort++;
99          *dstShort++ = SWAPSHORT(tmpShort);
100        }
101
102        RELEASECRITICAL(bytes, env, src, JNI_ABORT);
103
104        length -= size;
105        dstAddr += size;
106        srcPos += size;
107    }
108}
109
110JNIEXPORT void JNICALL
111Java_java_nio_Bits_copyToShortArray(JNIEnv *env, jobject this, jlong srcAddr,
112                                    jobject dst, jlong dstPos, jlong length)
113{
114    jbyte *bytes;
115    size_t size;
116    jshort *srcShort, *dstShort, *endShort;
117    jshort tmpShort;
118
119    srcShort = (jshort *)jlong_to_ptr(srcAddr);
120
121    while (length > 0) {
122        /* do not change this if-else statement, see WARNING above */
123        if (length > MBYTE)
124            size = MBYTE;
125        else
126            size = (size_t)length;
127
128        GETCRITICAL(bytes, env, dst);
129
130        dstShort = (jshort *)(bytes + dstPos);
131        endShort = srcShort + (size / sizeof(jshort));
132        while (srcShort < endShort) {
133            tmpShort = *srcShort++;
134            *dstShort++ = SWAPSHORT(tmpShort);
135        }
136
137        RELEASECRITICAL(bytes, env, dst, 0);
138
139        length -= size;
140        srcAddr += size;
141        dstPos += size;
142    }
143}
144
145JNIEXPORT void JNICALL
146Java_java_nio_Bits_copyFromIntArray(JNIEnv *env, jobject this, jobject src,
147                                    jlong srcPos, jlong dstAddr, jlong length)
148{
149    jbyte *bytes;
150    size_t size;
151    jint *srcInt, *dstInt, *endInt;
152    jint tmpInt;
153
154    dstInt = (jint *)jlong_to_ptr(dstAddr);
155
156    while (length > 0) {
157        /* do not change this code, see WARNING above */
158        if (length > MBYTE)
159            size = MBYTE;
160        else
161            size = (size_t)length;
162
163        GETCRITICAL(bytes, env, src);
164
165        srcInt = (jint *)(bytes + srcPos);
166        endInt = srcInt + (size / sizeof(jint));
167        while (srcInt < endInt) {
168            tmpInt = *srcInt++;
169            *dstInt++ = SWAPINT(tmpInt);
170        }
171
172        RELEASECRITICAL(bytes, env, src, JNI_ABORT);
173
174        length -= size;
175        dstAddr += size;
176        srcPos += size;
177    }
178}
179
180JNIEXPORT void JNICALL
181Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jobject this, jlong srcAddr,
182                                  jobject dst, jlong dstPos, jlong length)
183{
184    jbyte *bytes;
185    size_t size;
186    jint *srcInt, *dstInt, *endInt;
187    jint tmpInt;
188
189    srcInt = (jint *)jlong_to_ptr(srcAddr);
190
191    while (length > 0) {
192        /* do not change this code, see WARNING above */
193        if (length > MBYTE)
194            size = MBYTE;
195        else
196            size = (size_t)length;
197
198        GETCRITICAL(bytes, env, dst);
199
200        dstInt = (jint *)(bytes + dstPos);
201        endInt = srcInt + (size / sizeof(jint));
202        while (srcInt < endInt) {
203            tmpInt = *srcInt++;
204            *dstInt++ = SWAPINT(tmpInt);
205        }
206
207        RELEASECRITICAL(bytes, env, dst, 0);
208
209        length -= size;
210        srcAddr += size;
211        dstPos += size;
212    }
213}
214
215JNIEXPORT void JNICALL
216Java_java_nio_Bits_copyFromLongArray(JNIEnv *env, jobject this, jobject src,
217                                     jlong srcPos, jlong dstAddr, jlong length)
218{
219    jbyte *bytes;
220    size_t size;
221    jlong *srcLong, *dstLong, *endLong;
222    jlong tmpLong;
223
224    dstLong = (jlong *)jlong_to_ptr(dstAddr);
225
226    while (length > 0) {
227        /* do not change this code, see WARNING above */
228        if (length > MBYTE)
229            size = MBYTE;
230        else
231            size = (size_t)length;
232
233        GETCRITICAL(bytes, env, src);
234
235        srcLong = (jlong *)(bytes + srcPos);
236        endLong = srcLong + (size / sizeof(jlong));
237        while (srcLong < endLong) {
238            tmpLong = *srcLong++;
239            *dstLong++ = SWAPLONG(tmpLong);
240        }
241
242        RELEASECRITICAL(bytes, env, src, JNI_ABORT);
243
244        length -= size;
245        dstAddr += size;
246        srcPos += size;
247    }
248}
249
250JNIEXPORT void JNICALL
251Java_java_nio_Bits_copyToLongArray(JNIEnv *env, jobject this, jlong srcAddr,
252                                   jobject dst, jlong dstPos, jlong length)
253{
254    jbyte *bytes;
255    size_t size;
256    jlong *srcLong, *dstLong, *endLong;
257    jlong tmpLong;
258
259    srcLong = (jlong *)jlong_to_ptr(srcAddr);
260
261    while (length > 0) {
262        /* do not change this code, see WARNING above */
263        if (length > MBYTE)
264            size = MBYTE;
265        else
266            size = (size_t)length;
267
268        GETCRITICAL(bytes, env, dst);
269
270        dstLong = (jlong *)(bytes + dstPos);
271        endLong = srcLong + (size / sizeof(jlong));
272        while (srcLong < endLong) {
273            tmpLong = *srcLong++;
274            *dstLong++ = SWAPLONG(tmpLong);
275        }
276
277        RELEASECRITICAL(bytes, env, dst, 0);
278
279        length -= size;
280        srcAddr += size;
281        dstPos += size;
282    }
283}
284
285static JNINativeMethod gMethods[] = {
286    NATIVE_METHOD(Bits, copyFromShortArray, "(Ljava/lang/Object;JJJ)V"),
287    NATIVE_METHOD(Bits, copyToShortArray, "(JLjava/lang/Object;JJ)V"),
288    NATIVE_METHOD(Bits, copyFromIntArray, "(Ljava/lang/Object;JJJ)V"),
289    NATIVE_METHOD(Bits, copyToIntArray, "(JLjava/lang/Object;JJ)V"),
290    NATIVE_METHOD(Bits, copyFromLongArray, "(Ljava/lang/Object;JJJ)V"),
291    NATIVE_METHOD(Bits, copyToLongArray, "(JLjava/lang/Object;JJ)V"),
292};
293
294void register_java_nio_Bits(JNIEnv* env) {
295    jniRegisterNativeMethods(env, "java/nio/Bits", gMethods, NELEM(gMethods));
296}
297