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