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, *endShort;
  62     unsigned char* dst;
  63 
  64     dst = 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 = (jshort *)(bytes + srcPos + size);
  73         while (srcShort < endShort) {
  74             jshort tmp = SWAPSHORT(*srcShort);
  75             memcpy(dst, &tmp, sizeof(jshort));
  76             srcShort++;
  77             dst += sizeof(jshort);
  78         }
  79 
  80         RELEASECRITICAL(bytes, env, src, JNI_ABORT);
  81 
  82         length -= size;
  83         srcPos += size;
  84     }
  85 }
  86 
  87 JNIEXPORT void JNICALL
  88 Java_java_nio_Bits_copyToShortArray(JNIEnv *env, jclass clazz, jlong srcAddr,
  89                                     jobject dst, jlong dstPos, jlong length)
  90 {
  91     jbyte *bytes;
  92     size_t size;
  93     jshort *dstShort;
  94 
  95     unsigned char *src, *end;
  96     src = jlong_to_ptr(srcAddr);
  97 
  98     while (length > 0) {
  99         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
 100 
 101         GETCRITICAL_OR_RETURN(bytes, env, dst);
 102 
 103         dstShort = (jshort *)(bytes + dstPos);
 104         end = src + size;
 105         while (src < end) {
 106             jshort tmp;
 107             memcpy(&tmp, src, sizeof(jshort));
 108             *dstShort++ = SWAPSHORT(tmp);
 109             src += sizeof(jshort);
 110         }
 111 
 112         RELEASECRITICAL(bytes, env, dst, 0);
 113 
 114         length -= size;
 115         dstPos += size;
 116     }
 117 }
 118 
 119 JNIEXPORT void JNICALL
 120 Java_java_nio_Bits_copyFromIntArray(JNIEnv *env, jclass clazz, jobject src,
 121                                     jlong srcPos, jlong dstAddr, jlong length)
 122 {
 123     jbyte *bytes;
 124     size_t size;
 125     jint *srcInt, *endInt;
 126     unsigned char *dst;
 127 
 128     dst = jlong_to_ptr(dstAddr);
 129 
 130     while (length > 0) {
 131         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
 132 
 133         GETCRITICAL_OR_RETURN(bytes, env, src);
 134 
 135         srcInt = (jint *)(bytes + srcPos);
 136         endInt = (jint *)(bytes + srcPos + size);
 137         while (srcInt < endInt) {
 138             jint tmp = SWAPINT(*srcInt);
 139             memcpy(dst, &tmp, sizeof(jint));
 140             srcInt++;
 141             dst += sizeof(jint);
 142         }
 143 
 144         RELEASECRITICAL(bytes, env, src, JNI_ABORT);
 145 
 146         length -= size;
 147         srcPos += size;
 148     }
 149 }
 150 
 151 JNIEXPORT void JNICALL
 152 Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jclass clazz, jlong srcAddr,
 153                                   jobject dst, jlong dstPos, jlong length)
 154 {
 155     jbyte *bytes;
 156     size_t size;
 157     unsigned char *src, *end;
 158     jint *dstInt;
 159 
 160     src = jlong_to_ptr(srcAddr);
 161 
 162     while (length > 0) {
 163         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
 164 
 165         GETCRITICAL_OR_RETURN(bytes, env, dst);
 166 
 167         dstInt = (jint *)(bytes + dstPos);
 168         end = src + size;
 169         while (src < end) {
 170             jint tmp;
 171             memcpy(&tmp, src, sizeof(jint));
 172             *dstInt++ = SWAPINT(tmp);
 173             src += sizeof(jint);
 174         }
 175 
 176         RELEASECRITICAL(bytes, env, dst, 0);
 177 
 178         length -= size;
 179         dstPos += size;
 180     }
 181 }
 182 
 183 JNIEXPORT void JNICALL
 184 Java_java_nio_Bits_copyFromLongArray(JNIEnv *env, jclass clazz, jobject src,
 185                                      jlong srcPos, jlong dstAddr, jlong length)
 186 {
 187     jbyte *bytes;
 188     size_t size;
 189     jlong *srcLong, *endLong;
 190     unsigned char* dst;
 191 
 192     dst = jlong_to_ptr(dstAddr);
 193 
 194     while (length > 0) {
 195         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
 196 
 197         GETCRITICAL_OR_RETURN(bytes, env, src);
 198 
 199         srcLong = (jlong *)(bytes + srcPos);
 200         endLong = (jlong *)(bytes + srcPos + size);
 201         while (srcLong < endLong) {
 202             jlong tmp = SWAPLONG(*srcLong);
 203             memcpy(dst, &tmp, sizeof(jlong));
 204             srcLong++;
 205             dst += sizeof(jlong);
 206         }
 207 
 208         RELEASECRITICAL(bytes, env, src, JNI_ABORT);
 209 
 210         length -= size;
 211         srcPos += size;
 212     }
 213 }
 214 
 215 JNIEXPORT void JNICALL
 216 Java_java_nio_Bits_copyToLongArray(JNIEnv *env, jclass clazz, jlong srcAddr,
 217                                    jobject dst, jlong dstPos, jlong length)
 218 {
 219     jbyte *bytes;
 220     size_t size;
 221     unsigned char *src, *end;
 222     jlong *dstLong;
 223 
 224     src = jlong_to_ptr(srcAddr);
 225 
 226     while (length > 0) {
 227         size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
 228 
 229         GETCRITICAL_OR_RETURN(bytes, env, dst);
 230 
 231         dstLong = (jlong *)(bytes + dstPos);
 232         end = src + size;
 233         while (src < end) {
 234             jlong tmp;
 235             memcpy(&tmp, src, sizeof(jlong));
 236             *dstLong++ = SWAPLONG(tmp);
 237             src += sizeof(jlong);
 238         }
 239 
 240         RELEASECRITICAL(bytes, env, dst, 0);
 241 
 242         length -= size;
 243         dstPos += size;
 244     }
 245 }