1 /*
2  * Copyright (c) 1996, 2011, 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 #include "jni.h"
27 #include "jvm.h"
28 #include "jni_util.h"
29 #include "jlong.h"
30 
31 #include "java_lang_Float.h"
32 #include "java_lang_Double.h"
33 #include "java_io_ObjectInputStream.h"
34 
35 
36 /*
37  * Class:     java_io_ObjectInputStream
38  * Method:    bytesToFloats
39  * Signature: ([BI[FII)V
40  *
41  * Reconstitutes nfloats float values from their byte representations.  Byte
42  * values are read from array src starting at offset srcpos; the resulting
43  * float values are written to array dst starting at dstpos.
44  */
45 JNIEXPORT void JNICALL
Java_java_io_ObjectInputStream_bytesToFloats(JNIEnv * env,jclass this,jbyteArray src,jint srcpos,jfloatArray dst,jint dstpos,jint nfloats)46 Java_java_io_ObjectInputStream_bytesToFloats(JNIEnv *env,
47                                              jclass this,
48                                              jbyteArray src,
49                                              jint srcpos,
50                                              jfloatArray dst,
51                                              jint dstpos,
52                                              jint nfloats)
53 {
54     union {
55         int i;
56         float f;
57     } u;
58     jfloat *floats;
59     jbyte *bytes;
60     jsize dstend;
61     jint ival;
62 
63     if (nfloats == 0)
64         return;
65 
66     /* fetch source array */
67     if (src == NULL) {
68         JNU_ThrowNullPointerException(env, NULL);
69         return;
70     }
71     bytes = (*env)->GetPrimitiveArrayCritical(env, src, NULL);
72     if (bytes == NULL)          /* exception thrown */
73         return;
74 
75     /* fetch dest array */
76     if (dst == NULL) {
77         (*env)->ReleasePrimitiveArrayCritical(env, src, bytes, JNI_ABORT);
78         JNU_ThrowNullPointerException(env, NULL);
79         return;
80     }
81     floats = (*env)->GetPrimitiveArrayCritical(env, dst, NULL);
82     if (floats == NULL) {       /* exception thrown */
83         (*env)->ReleasePrimitiveArrayCritical(env, src, bytes, JNI_ABORT);
84         return;
85     }
86 
87     /* do conversion */
88     dstend = dstpos + nfloats;
89     for ( ; dstpos < dstend; dstpos++) {
90         ival = ((bytes[srcpos + 0] & 0xFF) << 24) +
91                ((bytes[srcpos + 1] & 0xFF) << 16) +
92                ((bytes[srcpos + 2] & 0xFF) << 8) +
93                ((bytes[srcpos + 3] & 0xFF) << 0);
94         u.i = (long) ival;
95         floats[dstpos] = (jfloat) u.f;
96         srcpos += 4;
97     }
98 
99     (*env)->ReleasePrimitiveArrayCritical(env, src, bytes, JNI_ABORT);
100     (*env)->ReleasePrimitiveArrayCritical(env, dst, floats, 0);
101 }
102 
103 /*
104  * Class:     java_io_ObjectInputStream
105  * Method:    bytesToDoubles
106  * Signature: ([BI[DII)V
107  *
108  * Reconstitutes ndoubles double values from their byte representations.
109  * Byte values are read from array src starting at offset srcpos; the
110  * resulting double values are written to array dst starting at dstpos.
111  */
112 JNIEXPORT void JNICALL
Java_java_io_ObjectInputStream_bytesToDoubles(JNIEnv * env,jclass this,jbyteArray src,jint srcpos,jdoubleArray dst,jint dstpos,jint ndoubles)113 Java_java_io_ObjectInputStream_bytesToDoubles(JNIEnv *env,
114                                               jclass this,
115                                               jbyteArray src,
116                                               jint srcpos,
117                                               jdoubleArray dst,
118                                               jint dstpos,
119                                               jint ndoubles)
120 
121 {
122     union {
123         jlong l;
124         double d;
125     } u;
126     jdouble *doubles;
127     jbyte *bytes;
128     jsize dstend;
129     jlong lval;
130 
131     if (ndoubles == 0)
132         return;
133 
134     /* fetch source array */
135     if (src == NULL) {
136         JNU_ThrowNullPointerException(env, NULL);
137         return;
138     }
139     bytes = (*env)->GetPrimitiveArrayCritical(env, src, NULL);
140     if (bytes == NULL)          /* exception thrown */
141         return;
142 
143     /* fetch dest array */
144     if (dst == NULL) {
145         (*env)->ReleasePrimitiveArrayCritical(env, src, bytes, JNI_ABORT);
146         JNU_ThrowNullPointerException(env, NULL);
147         return;
148     }
149     doubles = (*env)->GetPrimitiveArrayCritical(env, dst, NULL);
150     if (doubles == NULL) {      /* exception thrown */
151         (*env)->ReleasePrimitiveArrayCritical(env, src, bytes, JNI_ABORT);
152         return;
153     }
154 
155     /* do conversion */
156     dstend = dstpos + ndoubles;
157     for ( ; dstpos < dstend; dstpos++) {
158         lval = (((jlong) bytes[srcpos + 0] & 0xFF) << 56) +
159                (((jlong) bytes[srcpos + 1] & 0xFF) << 48) +
160                (((jlong) bytes[srcpos + 2] & 0xFF) << 40) +
161                (((jlong) bytes[srcpos + 3] & 0xFF) << 32) +
162                (((jlong) bytes[srcpos + 4] & 0xFF) << 24) +
163                (((jlong) bytes[srcpos + 5] & 0xFF) << 16) +
164                (((jlong) bytes[srcpos + 6] & 0xFF) << 8) +
165                (((jlong) bytes[srcpos + 7] & 0xFF) << 0);
166         jlong_to_jdouble_bits(&lval);
167         u.l = lval;
168         doubles[dstpos] = (jdouble) u.d;
169         srcpos += 8;
170     }
171 
172     (*env)->ReleasePrimitiveArrayCritical(env, src, bytes, JNI_ABORT);
173     (*env)->ReleasePrimitiveArrayCritical(env, dst, doubles, 0);
174 }
175 
176