diff options
Diffstat (limited to 'libjava/java/lang/natDouble.cc')
-rw-r--r-- | libjava/java/lang/natDouble.cc | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/libjava/java/lang/natDouble.cc b/libjava/java/lang/natDouble.cc new file mode 100644 index 00000000000..17990884751 --- /dev/null +++ b/libjava/java/lang/natDouble.cc @@ -0,0 +1,180 @@ +// natDouble.cc - Implementation of java.lang.Double native methods. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +/* AIX requires this to be the first thing in the file. */ +#ifndef __GNUC__ +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +#endif + +#include <stdlib.h> + +#include <cni.h> +#include <java/lang/String.h> +#include <java/lang/Double.h> +#include <java/lang/NumberFormatException.h> +#include <jvm.h> + +#include <stdio.h> +#include <string.h> + +#include "mprec.h" + +union u +{ + jlong l; + jdouble d; +}; + +jlong +java::lang::Double::doubleToLongBits(jdouble value) +{ + union u u; + u.d = value; + return u.l; +} + +jdouble +java::lang::Double::longBitsToDouble(jlong bits) +{ + union u u; + u.l = bits; + return u.d; +} + +jstring +java::lang::Double::toString(jdouble value, jboolean isFloat) +{ + if (isNaN (value)) + return JvNewStringLatin1 ("NaN", sizeof ("NaN") - 1); + + if (value == POSITIVE_INFINITY) + return JvNewStringLatin1 ("Infinity", sizeof ("Infinity") - 1); + + if (value == NEGATIVE_INFINITY) + return JvNewStringLatin1 ("-Infinity", sizeof ("-Infinity") - 1); + + char buffer[50], result[50]; + int decpt, sign; + + _dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int)isFloat); + + value = fabs (value); + + char *s = buffer; + char *d = result; + + if (sign) + *d++ = '-'; + + if (value >= 1e-3 && value < 1e7 || value == 0) + { + if (decpt <= 0) + *d++ = '0'; + else + { + for (int i = 0; i < decpt; i++) + if (*s) + *d++ = *s++; + else + *d++ = '0'; + } + + *d++ = '.'; + + if (*s == 0) + { + *d++ = '0'; + decpt++; + } + + while (decpt++ < 0) + *d++ = '0'; + + while (*s) + *d++ = *s++; + + *d = 0; + + return JvNewStringLatin1 (result, strlen (result)); + } + + *d++ = *s++; + decpt--; + *d++ = '.'; + + if (*s == 0) + *d++ = '0'; + + while (*s) + *d++ = *s++; + + *d++ = 'E'; + + if (decpt < 0) + { + *d++ = '-'; + decpt = -decpt; + } + + { + char exp[4]; + char *e = exp + sizeof exp; + + *--e = 0; + do + { + *--e = '0' + decpt % 10; + decpt /= 10; + } + while (decpt > 0); + + while (*e) + *d++ = *e++; + } + + *d = 0; + + return JvNewStringLatin1 (result, strlen (result)); +} + +jdouble +java::lang::Double::doubleValueOf(jstring str) +{ + int length = str->length(); + // Note that UTF can expand 3x. + +#ifdef HAVE_ALLOCA + char *data = (char *) alloca (3 * length + 1); +#else +#error --- need an alternate implementation here --- +#endif + + data[_Jv_GetStringUTFRegion (str, 0, length, data)] = 0; + + struct _Jv_reent reent; + memset (&reent, 0, sizeof reent); + + double val = _strtod_r (&reent, data, NULL); + + if (reent._errno) + _Jv_Throw (new NumberFormatException); + + return val; +} |