Reactos
at master 249 lines 5.6 kB view raw
1/* 2 * Copyright 2012 Jacek Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19#ifndef JSVAL_H 20#define JSVAL_H 21 22#include "jsstr.h" 23 24/* 25 * jsval_t structure is used to represent JavaScript dynamically-typed values. 26 * It's a (type,value) pair, usually represented as a structure of enum (type) 27 * and union (value of given type). For both memory and speed performance, we 28 * use tricks allowing storing both values as a struct with size equal to 29 * size of double (that is 64-bit) on 32-bit systems. For that, we use the fact 30 * that NaN value representation has 52 (almost) free bits. 31 */ 32 33#ifdef __i386__ 34#define JSVAL_DOUBLE_LAYOUT_PTR32 35#endif 36 37#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 38/* NaN exponent and our 0x80000 marker */ 39#define JSV_VAL(x) (0x7ff80000|x) 40#else 41#define JSV_VAL(x) x 42#endif 43 44typedef enum { 45 JSV_UNDEFINED = JSV_VAL(1), 46 JSV_NULL = JSV_VAL(2), 47 JSV_OBJECT = JSV_VAL(3), 48 JSV_STRING = JSV_VAL(4), 49 JSV_NUMBER = JSV_VAL(5), 50 JSV_BOOL = JSV_VAL(6), 51 JSV_VARIANT = JSV_VAL(7) 52} jsval_type_t; 53 54struct _jsval_t { 55#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 56 union { 57 double n; 58 struct { 59 union { 60 IDispatch *obj; 61 jsstr_t *str; 62 BOOL b; 63 VARIANT *v; 64 UINT_PTR as_uintptr; 65 } u; 66 jsval_type_t tag; 67 } s; 68 } u; 69#else 70 jsval_type_t type; 71 union { 72 IDispatch *obj; 73 jsstr_t *str; 74 double n; 75 BOOL b; 76 VARIANT *v; 77 } u; 78#endif 79}; 80 81#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 82 83C_ASSERT(sizeof(jsval_t) == sizeof(double)); 84 85#define __JSVAL_TYPE(x) ((x).u.s.tag) 86#define __JSVAL_BOOL(x) ((x).u.s.u.b) 87#define __JSVAL_STR(x) ((x).u.s.u.str) 88#define __JSVAL_OBJ(x) ((x).u.s.u.obj) 89#define __JSVAL_VAR(x) ((x).u.s.u.v) 90 91#else 92 93#define __JSVAL_TYPE(x) ((x).type) 94#define __JSVAL_BOOL(x) ((x).u.b) 95#define __JSVAL_STR(x) ((x).u.str) 96#define __JSVAL_OBJ(x) ((x).u.obj) 97#define __JSVAL_VAR(x) ((x).u.v) 98 99#endif 100 101static inline jsval_t jsval_bool(BOOL b) 102{ 103 jsval_t ret; 104 __JSVAL_TYPE(ret) = JSV_BOOL; 105 __JSVAL_BOOL(ret) = b; 106 return ret; 107} 108 109static inline jsval_t jsval_string(jsstr_t *str) 110{ 111 jsval_t ret; 112 __JSVAL_TYPE(ret) = JSV_STRING; 113 __JSVAL_STR(ret) = str; 114 return ret; 115} 116 117static inline jsval_t jsval_disp(IDispatch *obj) 118{ 119 jsval_t ret; 120 __JSVAL_TYPE(ret) = JSV_OBJECT; 121 __JSVAL_OBJ(ret) = obj; 122 return ret; 123} 124 125static inline jsval_t jsval_obj(jsdisp_t *obj) 126{ 127 return jsval_disp(to_disp(obj)); 128} 129 130static inline jsval_t jsval_null(void) 131{ 132 jsval_t ret; 133 __JSVAL_TYPE(ret) = JSV_NULL; 134 return ret; 135} 136 137static inline jsval_t jsval_undefined(void) 138{ 139 jsval_t ret; 140 __JSVAL_TYPE(ret) = JSV_UNDEFINED; 141 return ret; 142} 143 144static inline jsval_t jsval_number(double n) 145{ 146 jsval_t ret; 147#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 148 ret.u.n = n; 149 /* normalize NaN value */ 150 if((ret.u.s.tag & 0x7ff00000) == 0x7ff00000) { 151 /* isinf */ 152 if(ret.u.s.tag & 0xfffff) { 153 ret.u.s.tag = 0x7ff00000; 154 ret.u.s.u.as_uintptr = ~0; 155 }else if(ret.u.s.u.as_uintptr) { 156 ret.u.s.tag = 0x7ff00000; 157 } 158 } 159#else 160 ret.type = JSV_NUMBER; 161 ret.u.n = n; 162#endif 163 return ret; 164} 165 166static inline BOOL is_object_instance(jsval_t v) 167{ 168 return __JSVAL_TYPE(v) == JSV_OBJECT; 169} 170 171static inline BOOL is_undefined(jsval_t v) 172{ 173 return __JSVAL_TYPE(v) == JSV_UNDEFINED; 174} 175 176static inline BOOL is_null(jsval_t v) 177{ 178 return __JSVAL_TYPE(v) == JSV_NULL; 179} 180 181static inline BOOL is_null_instance(jsval_t v) 182{ 183 return is_null(v) || (is_object_instance(v) && !__JSVAL_OBJ(v)); 184} 185 186static inline BOOL is_string(jsval_t v) 187{ 188 return __JSVAL_TYPE(v) == JSV_STRING; 189} 190 191static inline BOOL is_number(jsval_t v) 192{ 193#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 194 return (v.u.s.tag & 0x7ff80000) != 0x7ff80000; 195#else 196 return v.type == JSV_NUMBER; 197#endif 198} 199 200static inline BOOL is_variant(jsval_t v) 201{ 202 return __JSVAL_TYPE(v) == JSV_VARIANT; 203} 204 205static inline BOOL is_bool(jsval_t v) 206{ 207 return __JSVAL_TYPE(v) == JSV_BOOL; 208} 209 210static inline jsval_type_t jsval_type(jsval_t v) 211{ 212#ifdef JSVAL_DOUBLE_LAYOUT_PTR32 213 return is_number(v) ? JSV_NUMBER : v.u.s.tag; 214#else 215 return v.type; 216#endif 217} 218 219static inline IDispatch *get_object(jsval_t v) 220{ 221 return __JSVAL_OBJ(v); 222} 223 224static inline double get_number(jsval_t v) 225{ 226 return v.u.n; 227} 228 229static inline jsstr_t *get_string(jsval_t v) 230{ 231 return __JSVAL_STR(v); 232} 233 234static inline VARIANT *get_variant(jsval_t v) 235{ 236 return __JSVAL_VAR(v); 237} 238 239static inline BOOL get_bool(jsval_t v) 240{ 241 return __JSVAL_BOOL(v); 242} 243 244HRESULT variant_to_jsval(VARIANT*,jsval_t*) DECLSPEC_HIDDEN; 245HRESULT jsval_to_variant(jsval_t,VARIANT*) DECLSPEC_HIDDEN; 246void jsval_release(jsval_t) DECLSPEC_HIDDEN; 247HRESULT jsval_copy(jsval_t,jsval_t*) DECLSPEC_HIDDEN; 248 249#endif