js/src/jsnum.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jsnum.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,333 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef jsnum_h
    1.11 +#define jsnum_h
    1.12 +
    1.13 +#include "mozilla/FloatingPoint.h"
    1.14 +
    1.15 +#include "NamespaceImports.h"
    1.16 +
    1.17 +#include "vm/NumericConversions.h"
    1.18 +
    1.19 +namespace js {
    1.20 +
    1.21 +class StringBuffer;
    1.22 +
    1.23 +extern bool
    1.24 +InitRuntimeNumberState(JSRuntime *rt);
    1.25 +
    1.26 +#if !EXPOSE_INTL_API
    1.27 +extern void
    1.28 +FinishRuntimeNumberState(JSRuntime *rt);
    1.29 +#endif
    1.30 +
    1.31 +} /* namespace js */
    1.32 +
    1.33 +/* Initialize the Number class, returning its prototype object. */
    1.34 +extern JSObject *
    1.35 +js_InitNumberClass(JSContext *cx, js::HandleObject obj);
    1.36 +
    1.37 +/*
    1.38 + * String constants for global function names, used in jsapi.c and jsnum.c.
    1.39 + */
    1.40 +extern const char js_isNaN_str[];
    1.41 +extern const char js_isFinite_str[];
    1.42 +extern const char js_parseFloat_str[];
    1.43 +extern const char js_parseInt_str[];
    1.44 +
    1.45 +class JSAtom;
    1.46 +
    1.47 +namespace js {
    1.48 +
    1.49 +/*
    1.50 + * When base == 10, this function implements ToString() as specified by
    1.51 + * ECMA-262-5 section 9.8.1; but note that it handles integers specially for
    1.52 + * performance.  See also js::NumberToCString().
    1.53 + */
    1.54 +template <js::AllowGC allowGC>
    1.55 +extern JSString *
    1.56 +NumberToString(js::ThreadSafeContext *cx, double d);
    1.57 +
    1.58 +extern JSAtom *
    1.59 +NumberToAtom(js::ExclusiveContext *cx, double d);
    1.60 +
    1.61 +template <AllowGC allowGC>
    1.62 +extern JSFlatString *
    1.63 +Int32ToString(ThreadSafeContext *cx, int32_t i);
    1.64 +
    1.65 +extern JSAtom *
    1.66 +Int32ToAtom(ExclusiveContext *cx, int32_t si);
    1.67 +
    1.68 +/*
    1.69 + * Convert an integer or double (contained in the given value) to a string and
    1.70 + * append to the given buffer.
    1.71 + */
    1.72 +extern bool JS_FASTCALL
    1.73 +NumberValueToStringBuffer(JSContext *cx, const Value &v, StringBuffer &sb);
    1.74 +
    1.75 +/* Same as js_NumberToString, different signature. */
    1.76 +extern JSFlatString *
    1.77 +NumberToString(JSContext *cx, double d);
    1.78 +
    1.79 +extern JSFlatString *
    1.80 +IndexToString(JSContext *cx, uint32_t index);
    1.81 +
    1.82 +/*
    1.83 + * Usually a small amount of static storage is enough, but sometimes we need
    1.84 + * to dynamically allocate much more.  This struct encapsulates that.
    1.85 + * Dynamically allocated memory will be freed when the object is destroyed.
    1.86 + */
    1.87 +struct ToCStringBuf
    1.88 +{
    1.89 +    /*
    1.90 +     * The longest possible result that would need to fit in sbuf is
    1.91 +     * (-0x80000000).toString(2), which has length 33.  Longer cases are
    1.92 +     * possible, but they'll go in dbuf.
    1.93 +     */
    1.94 +    static const size_t sbufSize = 34;
    1.95 +    char sbuf[sbufSize];
    1.96 +    char *dbuf;
    1.97 +
    1.98 +    ToCStringBuf();
    1.99 +    ~ToCStringBuf();
   1.100 +};
   1.101 +
   1.102 +/*
   1.103 + * Convert a number to a C string.  When base==10, this function implements
   1.104 + * ToString() as specified by ECMA-262-5 section 9.8.1.  It handles integral
   1.105 + * values cheaply.  Return nullptr if we ran out of memory.  See also
   1.106 + * js_NumberToCString().
   1.107 + */
   1.108 +extern char *
   1.109 +NumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base = 10);
   1.110 +
   1.111 +/*
   1.112 + * The largest positive integer such that all positive integers less than it
   1.113 + * may be precisely represented using the IEEE-754 double-precision format.
   1.114 + */
   1.115 +const double DOUBLE_INTEGRAL_PRECISION_LIMIT = uint64_t(1) << 53;
   1.116 +
   1.117 +/*
   1.118 + * Parse a decimal number encoded in |chars|.  The decimal number must be
   1.119 + * sufficiently small that it will not overflow the integrally-precise range of
   1.120 + * the double type -- that is, the number will be smaller than
   1.121 + * DOUBLE_INTEGRAL_PRECISION_LIMIT
   1.122 + */
   1.123 +extern double
   1.124 +ParseDecimalNumber(const JS::TwoByteChars chars);
   1.125 +
   1.126 +/*
   1.127 + * Compute the positive integer of the given base described immediately at the
   1.128 + * start of the range [start, end) -- no whitespace-skipping, no magical
   1.129 + * leading-"0" octal or leading-"0x" hex behavior, no "+"/"-" parsing, just
   1.130 + * reading the digits of the integer.  Return the index one past the end of the
   1.131 + * digits of the integer in *endp, and return the integer itself in *dp.  If
   1.132 + * base is 10 or a power of two the returned integer is the closest possible
   1.133 + * double; otherwise extremely large integers may be slightly inaccurate.
   1.134 + *
   1.135 + * If [start, end) does not begin with a number with the specified base,
   1.136 + * *dp == 0 and *endp == start upon return.
   1.137 + */
   1.138 +extern bool
   1.139 +GetPrefixInteger(ThreadSafeContext *cx, const jschar *start, const jschar *end, int base,
   1.140 +                 const jschar **endp, double *dp);
   1.141 +
   1.142 +/*
   1.143 + * This is like GetPrefixInteger, but only deals with base 10, and doesn't have
   1.144 + * and |endp| outparam.  It should only be used when the jschars are known to
   1.145 + * only contain digits.
   1.146 + */
   1.147 +extern bool
   1.148 +GetDecimalInteger(ExclusiveContext *cx, const jschar *start, const jschar *end, double *dp);
   1.149 +
   1.150 +extern bool
   1.151 +StringToNumber(ThreadSafeContext *cx, JSString *str, double *result);
   1.152 +
   1.153 +/* ES5 9.3 ToNumber, overwriting *vp with the appropriate number value. */
   1.154 +MOZ_ALWAYS_INLINE bool
   1.155 +ToNumber(JSContext *cx, JS::MutableHandleValue vp)
   1.156 +{
   1.157 +    if (vp.isNumber())
   1.158 +        return true;
   1.159 +    double d;
   1.160 +    extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext *cx, Value v, double *dp);
   1.161 +    if (!ToNumberSlow(cx, vp, &d))
   1.162 +        return false;
   1.163 +
   1.164 +    vp.setNumber(d);
   1.165 +    return true;
   1.166 +}
   1.167 +
   1.168 +bool
   1.169 +num_parseInt(JSContext *cx, unsigned argc, Value *vp);
   1.170 +
   1.171 +}  /* namespace js */
   1.172 +
   1.173 +/*
   1.174 + * Similar to strtod except that it replaces overflows with infinities of the
   1.175 + * correct sign, and underflows with zeros of the correct sign.  Guaranteed to
   1.176 + * return the closest double number to the given input in dp.
   1.177 + *
   1.178 + * Also allows inputs of the form [+|-]Infinity, which produce an infinity of
   1.179 + * the appropriate sign.  The case of the "Infinity" string must match exactly.
   1.180 + * If the string does not contain a number, set *ep to s and return 0.0 in dp.
   1.181 + * Return false if out of memory.
   1.182 + */
   1.183 +extern bool
   1.184 +js_strtod(js::ThreadSafeContext *cx, const jschar *s, const jschar *send,
   1.185 +          const jschar **ep, double *dp);
   1.186 +
   1.187 +extern bool
   1.188 +js_num_toString(JSContext *cx, unsigned argc, js::Value *vp);
   1.189 +
   1.190 +extern bool
   1.191 +js_num_valueOf(JSContext *cx, unsigned argc, js::Value *vp);
   1.192 +
   1.193 +namespace js {
   1.194 +
   1.195 +static MOZ_ALWAYS_INLINE bool
   1.196 +ValueFitsInInt32(const Value &v, int32_t *pi)
   1.197 +{
   1.198 +    if (v.isInt32()) {
   1.199 +        *pi = v.toInt32();
   1.200 +        return true;
   1.201 +    }
   1.202 +    return v.isDouble() && mozilla::NumberIsInt32(v.toDouble(), pi);
   1.203 +}
   1.204 +
   1.205 +/*
   1.206 + * Returns true if the given value is definitely an index: that is, the value
   1.207 + * is a number that's an unsigned 32-bit integer.
   1.208 + *
   1.209 + * This method prioritizes common-case speed over accuracy in every case.  It
   1.210 + * can produce false negatives (but not false positives): some values which are
   1.211 + * indexes will be reported not to be indexes by this method.  Users must
   1.212 + * consider this possibility when using this method.
   1.213 + */
   1.214 +static MOZ_ALWAYS_INLINE bool
   1.215 +IsDefinitelyIndex(const Value &v, uint32_t *indexp)
   1.216 +{
   1.217 +    if (v.isInt32() && v.toInt32() >= 0) {
   1.218 +        *indexp = v.toInt32();
   1.219 +        return true;
   1.220 +    }
   1.221 +
   1.222 +    int32_t i;
   1.223 +    if (v.isDouble() && mozilla::NumberIsInt32(v.toDouble(), &i) && i >= 0) {
   1.224 +        *indexp = uint32_t(i);
   1.225 +        return true;
   1.226 +    }
   1.227 +
   1.228 +    return false;
   1.229 +}
   1.230 +
   1.231 +/* ES5 9.4 ToInteger. */
   1.232 +static inline bool
   1.233 +ToInteger(JSContext *cx, HandleValue v, double *dp)
   1.234 +{
   1.235 +    if (v.isInt32()) {
   1.236 +        *dp = v.toInt32();
   1.237 +        return true;
   1.238 +    }
   1.239 +    if (v.isDouble()) {
   1.240 +        *dp = v.toDouble();
   1.241 +    } else {
   1.242 +        extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext *cx, Value v, double *dp);
   1.243 +        if (!ToNumberSlow(cx, v, dp))
   1.244 +            return false;
   1.245 +    }
   1.246 +    *dp = ToInteger(*dp);
   1.247 +    return true;
   1.248 +}
   1.249 +
   1.250 +inline bool
   1.251 +SafeAdd(int32_t one, int32_t two, int32_t *res)
   1.252 +{
   1.253 +    // Use unsigned for the 32-bit operation since signed overflow gets
   1.254 +    // undefined behavior.
   1.255 +    *res = uint32_t(one) + uint32_t(two);
   1.256 +    int64_t ores = (int64_t)one + (int64_t)two;
   1.257 +    return ores == (int64_t)*res;
   1.258 +}
   1.259 +
   1.260 +inline bool
   1.261 +SafeSub(int32_t one, int32_t two, int32_t *res)
   1.262 +{
   1.263 +    *res = uint32_t(one) - uint32_t(two);
   1.264 +    int64_t ores = (int64_t)one - (int64_t)two;
   1.265 +    return ores == (int64_t)*res;
   1.266 +}
   1.267 +
   1.268 +inline bool
   1.269 +SafeMul(int32_t one, int32_t two, int32_t *res)
   1.270 +{
   1.271 +    *res = uint32_t(one) * uint32_t(two);
   1.272 +    int64_t ores = (int64_t)one * (int64_t)two;
   1.273 +    return ores == (int64_t)*res;
   1.274 +}
   1.275 +
   1.276 +extern bool
   1.277 +ToNumberSlow(ExclusiveContext *cx, Value v, double *dp);
   1.278 +
   1.279 +// Variant of ToNumber which takes an ExclusiveContext instead of a JSContext.
   1.280 +// ToNumber is part of the API and can't use ExclusiveContext directly.
   1.281 +MOZ_ALWAYS_INLINE bool
   1.282 +ToNumber(ExclusiveContext *cx, const Value &v, double *out)
   1.283 +{
   1.284 +    if (v.isNumber()) {
   1.285 +        *out = v.toNumber();
   1.286 +        return true;
   1.287 +    }
   1.288 +    return ToNumberSlow(cx, v, out);
   1.289 +}
   1.290 +
   1.291 +/*
   1.292 + * Thread safe variants of number conversion functions.
   1.293 + */
   1.294 +
   1.295 +bool
   1.296 +NonObjectToNumberSlow(ThreadSafeContext *cx, Value v, double *out);
   1.297 +
   1.298 +inline bool
   1.299 +NonObjectToNumber(ThreadSafeContext *cx, const Value &v, double *out)
   1.300 +{
   1.301 +    if (v.isNumber()) {
   1.302 +        *out = v.toNumber();
   1.303 +        return true;
   1.304 +    }
   1.305 +    return NonObjectToNumberSlow(cx, v, out);
   1.306 +}
   1.307 +
   1.308 +bool
   1.309 +NonObjectToInt32Slow(ThreadSafeContext *cx, const Value &v, int32_t *out);
   1.310 +
   1.311 +inline bool
   1.312 +NonObjectToInt32(ThreadSafeContext *cx, const Value &v, int32_t *out)
   1.313 +{
   1.314 +    if (v.isInt32()) {
   1.315 +        *out = v.toInt32();
   1.316 +        return true;
   1.317 +    }
   1.318 +    return NonObjectToInt32Slow(cx, v, out);
   1.319 +}
   1.320 +
   1.321 +bool
   1.322 +NonObjectToUint32Slow(ThreadSafeContext *cx, const Value &v, uint32_t *out);
   1.323 +
   1.324 +MOZ_ALWAYS_INLINE bool
   1.325 +NonObjectToUint32(ThreadSafeContext *cx, const Value &v, uint32_t *out)
   1.326 +{
   1.327 +    if (v.isInt32()) {
   1.328 +        *out = uint32_t(v.toInt32());
   1.329 +        return true;
   1.330 +    }
   1.331 +    return NonObjectToUint32Slow(cx, v, out);
   1.332 +}
   1.333 +
   1.334 +} /* namespace js */
   1.335 +
   1.336 +#endif /* jsnum_h */

mercurial