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 */
45JNIEXPORT void JNICALL
46Java_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 */
112JNIEXPORT void JNICALL
113Java_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