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 #define MBYTE 1048576
  35 
  36 #define GETCRITICAL_OR_RETURN(bytes, env, obj) { \
  37     bytes = (*env)->GetPrimitiveArrayCritical(env, obj, NULL); \
  38     if (bytes == NULL)  { \
  39         if ((*env)->ExceptionOccurred(env) == NULL) \
  40             JNU_ThrowInternalError(env, "Unable to get array"); \
  41         return; \
  42     } \
  43 }
  44 
  45 #define RELEASECRITICAL(bytes, env, obj, mode) { \
  46     (*env)->ReleasePrimitiveArrayCritical(env, obj, bytes, mode); \
  47 }
  48 
  49 #define SWAPSHORT(x) ((jshort)(((x) << 8) | (((x) >> 8) & 0xff)))
  50 #define SWAPINT(x)   ((jint)((SWAPSHORT((jshort)(x)) << 16) | \
  51                             (SWAPSHORT((jshort)((x) >> 16)) & 0xffff)))
  52 #define SWAPLONG(x)  ((jlong)(((jlong)SWAPINT((jint)(x)) << 32) | \
  53                               ((jlong)SWAPINT((jint)((x) >> 32)) & 0xffffffff)))
  54 
  55 JNIEXPORT void JNICALL
  56 Java_java_nio_Bits_copyFromShortArray(JNIEnv *env, jclass clazz, jobject src,
  57                                       jlong srcPos, jlong dstAddr, jlong length)
  58 {
  59     jbyte *bytes;
  60     size_t size;
  61     jshort *srcShort, *dstShort, *endShort;
  62     jshort tmpShort;
  63 
  64     dstShort = (jshort *)jlong_to_ptr(dstAddr);
  65 
  66     while (length > 0) {
  67         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
  68 
  69         GETCRITICAL_OR_RETURN(bytes, env, src);
  70 
  71         srcShort = (jshort *)(bytes + srcPos);
  72         endShort = srcShort + (size / sizeof(jshort));
  73         while (srcShort < endShort) {
  74           tmpShort = *srcShort++;
  75           *dstShort++ = SWAPSHORT(tmpShort);
  76         }
  77 
  78         RELEASECRITICAL(bytes, env, src, JNI_ABORT);
  79 
  80         length -= size;
  81         srcPos += size;
  82     }
  83 }
  84 
  85 JNIEXPORT void JNICALL
  86 Java_java_nio_Bits_copyToShortArray(JNIEnv *env, jclass clazz, jlong srcAddr,
  87                                     jobject dst, jlong dstPos, jlong length)
  88 {
  89     jbyte *bytes;
  90     size_t size;
  91     jshort *srcShort, *dstShort, *endShort;
  92     jshort tmpShort;
  93 
  94     srcShort = (jshort *)jlong_to_ptr(srcAddr);
  95 
  96     while (length > 0) {
  97         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
  98 
  99         GETCRITICAL_OR_RETURN(bytes, env, dst);
 100 
 101         dstShort = (jshort *)(bytes + dstPos);
 102         endShort = srcShort + (size / sizeof(jshort));
 103         while (srcShort < endShort) {
 104             tmpShort = *srcShort++;
 105             *dstShort++ = SWAPSHORT(tmpShort);
 106         }
 107 
 108         RELEASECRITICAL(bytes, env, dst, 0);
 109 
 110         length -= size;
 111         dstPos += size;
 112     }
 113 }
 114 
 115 JNIEXPORT void JNICALL
 116 Java_java_nio_Bits_copyFromIntArray(JNIEnv *env, jclass clazz, jobject src,
 117                                     jlong srcPos, jlong dstAddr, jlong length)
 118 {
 119     jbyte *bytes;
 120     size_t size;
 121     jint *srcInt, *dstInt, *endInt;
 122     jint tmpInt;
 123 
 124     dstInt = (jint *)jlong_to_ptr(dstAddr);
 125 
 126     while (length > 0) {
 127         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
 128 
 129         GETCRITICAL_OR_RETURN(bytes, env, src);
 130 
 131         srcInt = (jint *)(bytes + srcPos);
 132         endInt = srcInt + (size / sizeof(jint));
 133         while (srcInt < endInt) {
 134             tmpInt = *srcInt++;
 135             *dstInt++ = SWAPINT(tmpInt);
 136         }
 137 
 138         RELEASECRITICAL(bytes, env, src, JNI_ABORT);
 139 
 140         length -= size;
 141         srcPos += size;
 142     }
 143 }
 144 
 145 JNIEXPORT void JNICALL
 146 Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jclass clazz, jlong srcAddr,
 147                                   jobject dst, jlong dstPos, jlong length)
 148 {
 149     jbyte *bytes;
 150     size_t size;
 151     jint *srcInt, *dstInt, *endInt;
 152     jint tmpInt;
 153 
 154     srcInt = (jint *)jlong_to_ptr(srcAddr);
 155 
 156     while (length > 0) {
 157         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
 158 
 159         GETCRITICAL_OR_RETURN(bytes, env, dst);
 160 
 161         dstInt = (jint *)(bytes + dstPos);
 162         endInt = srcInt + (size / sizeof(jint));
 163         while (srcInt < endInt) {
 164             tmpInt = *srcInt++;
 165             *dstInt++ = SWAPINT(tmpInt);
 166         }
 167 
 168         RELEASECRITICAL(bytes, env, dst, 0);
 169 
 170         length -= size;
 171         dstPos += size;
 172     }
 173 }
 174 
 175 JNIEXPORT void JNICALL
 176 Java_java_nio_Bits_copyFromLongArray(JNIEnv *env, jclass clazz, jobject src,
 177                                      jlong srcPos, jlong dstAddr, jlong length)
 178 {
 179     jbyte *bytes;
 180     size_t size;
 181     jlong *srcLong, *dstLong, *endLong;
 182     jlong tmpLong;
 183 
 184     dstLong = (jlong *)jlong_to_ptr(dstAddr);
 185 
 186     while (length > 0) {
 187         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
 188 
 189         GETCRITICAL_OR_RETURN(bytes, env, src);
 190 
 191         srcLong = (jlong *)(bytes + srcPos);
 192         endLong = srcLong + (size / sizeof(jlong));
 193         while (srcLong < endLong) {
 194             tmpLong = *srcLong++;
 195             *dstLong++ = SWAPLONG(tmpLong);
 196         }
 197 
 198         RELEASECRITICAL(bytes, env, src, JNI_ABORT);
 199 
 200         length -= size;
 201         srcPos += size;
 202     }
 203 }
 204 
 205 JNIEXPORT void JNICALL
 206 Java_java_nio_Bits_copyToLongArray(JNIEnv *env, jclass clazz, jlong srcAddr,
 207                                    jobject dst, jlong dstPos, jlong length)
 208 {
 209     jbyte *bytes;
 210     size_t size;
 211     jlong *srcLong, *dstLong, *endLong;
 212     jlong tmpLong;
 213 
 214     srcLong = (jlong *)jlong_to_ptr(srcAddr);
 215 
 216     while (length > 0) {
 217         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
 218 
 219         GETCRITICAL_OR_RETURN(bytes, env, dst);
 220 
 221         dstLong = (jlong *)(bytes + dstPos);
 222         endLong = srcLong + (size / sizeof(jlong));
 223         while (srcLong < endLong) {
 224             tmpLong = *srcLong++;
 225             *dstLong++ = SWAPLONG(tmpLong);
 226         }
 227 
 228         RELEASECRITICAL(bytes, env, dst, 0);
 229 
 230         length -= size;
 231         dstPos += size;
 232     }
 233 }