1/*
2 * Copyright (c) 1999, 2013, 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_util.h"
27#include "jdk_util.h"
28
29#include "java_lang_Float.h"
30#include "java_lang_Double.h"
31#include "java_io_ObjectOutputStream.h"
32
33/*
34 * Class:     java_io_ObjectOutputStream
35 * Method:    floatsToBytes
36 * Signature: ([FI[BII)V
37 *
38 * Convert nfloats float values to their byte representations.  Float values
39 * are read from array src starting at offset srcpos and written to array
40 * dst starting at offset dstpos.
41 */
42JNIEXPORT void JNICALL
43Java_java_io_ObjectOutputStream_floatsToBytes(JNIEnv *env,
44                                              jclass this,
45                                              jfloatArray src,
46                                              jint srcpos,
47                                              jbyteArray dst,
48                                              jint dstpos,
49                                              jint nfloats)
50{
51    union {
52        int i;
53        float f;
54    } u;
55    jfloat *floats;
56    jbyte *bytes;
57    jsize srcend;
58    jint ival;
59    float fval;
60
61    if (nfloats == 0)
62        return;
63
64    /* fetch source array */
65    if (src == NULL) {
66        JNU_ThrowNullPointerException(env, NULL);
67        return;
68    }
69    floats = (*env)->GetPrimitiveArrayCritical(env, src, NULL);
70    if (floats == NULL)         /* exception thrown */
71        return;
72
73    /* fetch dest array */
74    if (dst == NULL) {
75        (*env)->ReleasePrimitiveArrayCritical(env, src, floats, JNI_ABORT);
76        JNU_ThrowNullPointerException(env, NULL);
77        return;
78    }
79    bytes = (*env)->GetPrimitiveArrayCritical(env, dst, NULL);
80    if (bytes == NULL) {        /* exception thrown */
81        (*env)->ReleasePrimitiveArrayCritical(env, src, floats, JNI_ABORT);
82        return;
83    }
84
85    /* do conversion */
86    srcend = srcpos + nfloats;
87    for ( ; srcpos < srcend; srcpos++) {
88        fval = (float) floats[srcpos];
89        if (ISNANF(fval)) {          /* collapse NaNs */
90            ival = 0x7fc00000;
91        } else {
92            u.f = fval;
93            ival = (jint) u.i;
94        }
95        bytes[dstpos++] = (ival >> 24) & 0xFF;
96        bytes[dstpos++] = (ival >> 16) & 0xFF;
97        bytes[dstpos++] = (ival >> 8) & 0xFF;
98        bytes[dstpos++] = (ival >> 0) & 0xFF;
99    }
100
101    (*env)->ReleasePrimitiveArrayCritical(env, src, floats, JNI_ABORT);
102    (*env)->ReleasePrimitiveArrayCritical(env, dst, bytes, 0);
103}
104
105/*
106 * Class:     java_io_ObjectOutputStream
107 * Method:    doublesToBytes
108 * Signature: ([DI[BII)V
109 *
110 * Convert ndoubles double values to their byte representations.  Double
111 * values are read from array src starting at offset srcpos and written to
112 * array dst starting at offset dstpos.
113 */
114JNIEXPORT void JNICALL
115Java_java_io_ObjectOutputStream_doublesToBytes(JNIEnv *env,
116                                               jclass this,
117                                               jdoubleArray src,
118                                               jint srcpos,
119                                               jbyteArray dst,
120                                               jint dstpos,
121                                               jint ndoubles)
122{
123    union {
124        jlong l;
125        double d;
126    } u;
127    jdouble *doubles;
128    jbyte *bytes;
129    jsize srcend;
130    jdouble dval;
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    doubles = (*env)->GetPrimitiveArrayCritical(env, src, NULL);
142    if (doubles == NULL)                /* exception thrown */
143        return;
144
145    /* fetch dest array */
146    if (dst == NULL) {
147        (*env)->ReleasePrimitiveArrayCritical(env, src, doubles, JNI_ABORT);
148        JNU_ThrowNullPointerException(env, NULL);
149        return;
150    }
151    bytes = (*env)->GetPrimitiveArrayCritical(env, dst, NULL);
152    if (bytes == NULL) {        /* exception thrown */
153        (*env)->ReleasePrimitiveArrayCritical(env, src, doubles, JNI_ABORT);
154        return;
155    }
156
157    /* do conversion */
158    srcend = srcpos + ndoubles;
159    for ( ; srcpos < srcend; srcpos++) {
160        dval = doubles[srcpos];
161        if (ISNAND((double) dval)) {         /* collapse NaNs */
162            lval = jint_to_jlong(0x7ff80000);
163            lval = jlong_shl(lval, 32);
164        } else {
165            jdouble_to_jlong_bits(&dval);
166            u.d = (double) dval;
167            lval = u.l;
168        }
169        bytes[dstpos++] = (lval >> 56) & 0xFF;
170        bytes[dstpos++] = (lval >> 48) & 0xFF;
171        bytes[dstpos++] = (lval >> 40) & 0xFF;
172        bytes[dstpos++] = (lval >> 32) & 0xFF;
173        bytes[dstpos++] = (lval >> 24) & 0xFF;
174        bytes[dstpos++] = (lval >> 16) & 0xFF;
175        bytes[dstpos++] = (lval >> 8) & 0xFF;
176        bytes[dstpos++] = (lval >> 0) & 0xFF;
177    }
178
179    (*env)->ReleasePrimitiveArrayCritical(env, src, doubles, JNI_ABORT);
180    (*env)->ReleasePrimitiveArrayCritical(env, dst, bytes, 0);
181}
182