jsval.h 5.45 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Copyright 2012 Jacek Caban for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#ifndef JSVAL_H
#define JSVAL_H

22 23
#include "jsstr.h"

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
/*
 * jsval_t structure is used to represent JavaScript dynamically-typed values.
 * It's a (type,value) pair, usually represented as a structure of enum (type)
 * and union (value of given type). For both memory and speed performance, we
 * use tricks allowing storing both values as a struct with size equal to
 * size of double (that is 64-bit) on 32-bit systems. For that, we use the fact
 * that NaN value representation has 52 (almost) free bits.
 */

#ifdef __i386__
#define JSVAL_DOUBLE_LAYOUT_PTR32
#endif

#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
/* NaN exponent and our 0x80000 marker */
#define JSV_VAL(x) (0x7ff80000|x)
#else
#define JSV_VAL(x) x
#endif

44
typedef enum {
45 46 47 48 49 50 51
    JSV_UNDEFINED = JSV_VAL(1),
    JSV_NULL      = JSV_VAL(2),
    JSV_OBJECT    = JSV_VAL(3),
    JSV_STRING    = JSV_VAL(4),
    JSV_NUMBER    = JSV_VAL(5),
    JSV_BOOL      = JSV_VAL(6),
    JSV_VARIANT   = JSV_VAL(7)
52 53 54
} jsval_type_t;

struct _jsval_t {
55 56 57 58 59 60
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
    union {
        double n;
        struct {
            union {
                IDispatch *obj;
61
                jsstr_t *str;
62 63 64 65 66 67 68 69
                BOOL b;
                VARIANT *v;
                UINT_PTR as_uintptr;
            } u;
            jsval_type_t tag;
        } s;
    } u;
#else
70 71 72
    jsval_type_t type;
    union {
        IDispatch *obj;
73
        jsstr_t *str;
74 75 76 77
        double n;
        BOOL b;
        VARIANT *v;
    } u;
78
#endif
79 80
};

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32

C_ASSERT(sizeof(jsval_t) == sizeof(double));

#define __JSVAL_TYPE(x) ((x).u.s.tag)
#define __JSVAL_BOOL(x) ((x).u.s.u.b)
#define __JSVAL_STR(x)  ((x).u.s.u.str)
#define __JSVAL_OBJ(x)  ((x).u.s.u.obj)
#define __JSVAL_VAR(x)  ((x).u.s.u.v)

#else

#define __JSVAL_TYPE(x) ((x).type)
#define __JSVAL_BOOL(x) ((x).u.b)
#define __JSVAL_STR(x)  ((x).u.str)
#define __JSVAL_OBJ(x)  ((x).u.obj)
#define __JSVAL_VAR(x)  ((x).u.v)

#endif

101 102 103
static inline jsval_t jsval_bool(BOOL b)
{
    jsval_t ret;
104 105
    __JSVAL_TYPE(ret) = JSV_BOOL;
    __JSVAL_BOOL(ret) = b;
106 107 108
    return ret;
}

109
static inline jsval_t jsval_string(jsstr_t *str)
110 111
{
    jsval_t ret;
112 113
    __JSVAL_TYPE(ret) = JSV_STRING;
    __JSVAL_STR(ret) = str;
114 115 116 117 118 119
    return ret;
}

static inline jsval_t jsval_disp(IDispatch *obj)
{
    jsval_t ret;
120 121
    __JSVAL_TYPE(ret) = JSV_OBJECT;
    __JSVAL_OBJ(ret) = obj;
122 123 124 125 126 127 128 129 130 131
    return ret;
}

static inline jsval_t jsval_obj(jsdisp_t *obj)
{
    return jsval_disp(to_disp(obj));
}

static inline jsval_t jsval_null(void)
{
132 133
    jsval_t ret;
    __JSVAL_TYPE(ret) = JSV_NULL;
134 135 136 137 138
    return ret;
}

static inline jsval_t jsval_undefined(void)
{
139 140
    jsval_t ret;
    __JSVAL_TYPE(ret) = JSV_UNDEFINED;
141 142 143 144 145 146
    return ret;
}

static inline jsval_t jsval_number(double n)
{
    jsval_t ret;
147 148 149 150 151 152 153 154 155 156 157 158 159
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
    ret.u.n = n;
    /* normalize NaN value */
    if((ret.u.s.tag & 0x7ff00000) == 0x7ff00000) {
        /* isinf */
        if(ret.u.s.tag & 0xfffff) {
            ret.u.s.tag = 0x7ff00000;
            ret.u.s.u.as_uintptr = ~0;
        }else if(ret.u.s.u.as_uintptr) {
            ret.u.s.tag = 0x7ff00000;
        }
    }
#else
160 161
    ret.type = JSV_NUMBER;
    ret.u.n = n;
162
#endif
163 164 165 166 167
    return ret;
}

static inline BOOL is_object_instance(jsval_t v)
{
168
    return __JSVAL_TYPE(v) == JSV_OBJECT;
169 170 171 172
}

static inline BOOL is_undefined(jsval_t v)
{
173
    return __JSVAL_TYPE(v) == JSV_UNDEFINED;
174 175 176 177
}

static inline BOOL is_null(jsval_t v)
{
178
    return __JSVAL_TYPE(v) == JSV_NULL;
179 180 181 182
}

static inline BOOL is_null_instance(jsval_t v)
{
183
    return is_null(v) || (is_object_instance(v) && !__JSVAL_OBJ(v));
184 185 186 187
}

static inline BOOL is_string(jsval_t v)
{
188
    return __JSVAL_TYPE(v) == JSV_STRING;
189 190 191 192
}

static inline BOOL is_number(jsval_t v)
{
193 194 195
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
    return (v.u.s.tag & 0x7ff80000) != 0x7ff80000;
#else
196
    return v.type == JSV_NUMBER;
197
#endif
198 199 200 201
}

static inline BOOL is_variant(jsval_t v)
{
202
    return __JSVAL_TYPE(v) == JSV_VARIANT;
203 204 205 206
}

static inline BOOL is_bool(jsval_t v)
{
207 208 209 210 211 212 213 214 215 216
    return __JSVAL_TYPE(v) == JSV_BOOL;
}

static inline jsval_type_t jsval_type(jsval_t v)
{
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
    return is_number(v) ? JSV_NUMBER : v.u.s.tag;
#else
    return v.type;
#endif
217 218 219 220
}

static inline IDispatch *get_object(jsval_t v)
{
221
    return __JSVAL_OBJ(v);
222 223 224 225 226 227 228
}

static inline double get_number(jsval_t v)
{
    return v.u.n;
}

229
static inline jsstr_t *get_string(jsval_t v)
230
{
231
    return __JSVAL_STR(v);
232 233 234 235
}

static inline VARIANT *get_variant(jsval_t v)
{
236
    return __JSVAL_VAR(v);
237 238 239 240
}

static inline BOOL get_bool(jsval_t v)
{
241
    return __JSVAL_BOOL(v);
242 243 244 245 246 247 248 249
}

HRESULT variant_to_jsval(VARIANT*,jsval_t*) DECLSPEC_HIDDEN;
HRESULT jsval_to_variant(jsval_t,VARIANT*) DECLSPEC_HIDDEN;
void jsval_release(jsval_t) DECLSPEC_HIDDEN;
HRESULT jsval_copy(jsval_t,jsval_t*) DECLSPEC_HIDDEN;

#endif