oleaut32: Make _argsize and _xsize receive the full TYPEDESC and parent ITypeInfo...
[wine] / dlls / jscript / jsutils.c
1 /*
2  * Copyright 2008 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 #include "jscript.h"
20
21 #include "wine/debug.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
24
25 const char *debugstr_variant(const VARIANT *v)
26 {
27     switch(V_VT(v)) {
28     case VT_EMPTY:
29         return wine_dbg_sprintf("{VT_EMPTY}");
30     case VT_NULL:
31         return wine_dbg_sprintf("{VT_NULL}");
32     case VT_I4:
33         return wine_dbg_sprintf("{VT_I4: %d}", V_I4(v));
34     case VT_R8:
35         return wine_dbg_sprintf("{VT_R8: %lf}", V_R8(v));
36     case VT_BSTR:
37         return wine_dbg_sprintf("{VT_BSTR: %s}", debugstr_w(V_BSTR(v)));
38     case VT_DISPATCH:
39         return wine_dbg_sprintf("{VT_DISPATCH: %p}", V_DISPATCH(v));
40     case VT_BOOL:
41         return wine_dbg_sprintf("{VT_BOOL: %x}", V_BOOL(v));
42     default:
43         return wine_dbg_sprintf("{vt %d}", V_VT(v));
44     }
45 }
46
47 #define MIN_BLOCK_SIZE  128
48
49 static inline DWORD block_size(DWORD block)
50 {
51     return MIN_BLOCK_SIZE << block;
52 }
53
54 void jsheap_init(jsheap_t *heap)
55 {
56     memset(heap, 0, sizeof(*heap));
57     list_init(&heap->custom_blocks);
58 }
59
60 void *jsheap_alloc(jsheap_t *heap, DWORD size)
61 {
62     struct list *list;
63     void *tmp;
64
65     if(!heap->block_cnt) {
66         if(!heap->blocks) {
67             heap->blocks = heap_alloc(sizeof(void*));
68             if(!heap->blocks)
69                 return NULL;
70         }
71
72         tmp = heap_alloc(block_size(0));
73         if(!tmp)
74             return NULL;
75
76         heap->blocks[0] = tmp;
77         heap->block_cnt = 1;
78     }
79
80     if(heap->offset + size < block_size(heap->last_block)) {
81         tmp = ((BYTE*)heap->blocks[heap->last_block])+heap->offset;
82         heap->offset += size;
83         return tmp;
84     }
85
86     if(size < block_size(heap->last_block+1)) {
87         if(heap->last_block+1 == heap->block_cnt) {
88             tmp = heap_realloc(heap->blocks, (heap->block_cnt+1)*sizeof(void*));
89             if(!tmp)
90                 return NULL;
91             heap->blocks = tmp;
92         }
93
94         tmp = heap_alloc(block_size(heap->block_cnt+1));
95         if(!tmp)
96             return NULL;
97
98         heap->blocks[heap->block_cnt++] = tmp;
99
100         heap->last_block++;
101         heap->offset = size;
102         return heap->blocks[heap->last_block];
103     }
104
105     list = heap_alloc(size + sizeof(struct list));
106     if(!list)
107         return NULL;
108
109     list_add_head(&heap->custom_blocks, list);
110     return list+1;
111 }
112
113 void jsheap_clear(jsheap_t *heap)
114 {
115     struct list *tmp;
116
117     while((tmp = list_next(&heap->custom_blocks, &heap->custom_blocks))) {
118         list_remove(tmp);
119         heap_free(tmp);
120     }
121 }
122
123 void jsheap_free(jsheap_t *heap)
124 {
125     DWORD i;
126
127     jsheap_clear(heap);
128
129     for(i=0; i < heap->block_cnt; i++)
130         heap_free(heap->blocks[i]);
131     heap_free(heap->blocks);
132
133     jsheap_init(heap);
134 }
135
136 /* ECMA-262 3rd Edition    9.1 */
137 HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
138 {
139     switch(V_VT(v)) {
140     case VT_EMPTY:
141     case VT_NULL:
142     case VT_BOOL:
143     case VT_I4:
144     case VT_R8:
145         *ret = *v;
146         break;
147     case VT_BSTR:
148         V_VT(ret) = VT_BSTR;
149         V_BSTR(ret) = SysAllocString(V_BSTR(v));
150         break;
151     case VT_DISPATCH:
152         return disp_propget(V_DISPATCH(v), DISPID_VALUE, ctx->lcid, ret, ei, NULL /*FIXME*/);
153     default:
154         FIXME("Unimplemented for vt %d\n", V_VT(v));
155         return E_NOTIMPL;
156     }
157
158     return S_OK;
159 }
160
161 /* ECMA-262 3rd Edition    9.2 */
162 HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b)
163 {
164     switch(V_VT(v)) {
165     case VT_EMPTY:
166     case VT_NULL:
167         *b = VARIANT_FALSE;
168         break;
169     case VT_I4:
170         *b = V_I4(v) ? VARIANT_TRUE : VARIANT_FALSE;
171         break;
172     case VT_R8:
173         *b = V_R8(v) ? VARIANT_TRUE : VARIANT_FALSE;
174         break;
175     case VT_BSTR:
176         *b = V_BSTR(v) && *V_BSTR(v) ? VARIANT_TRUE : VARIANT_FALSE;
177         break;
178     case VT_DISPATCH:
179         *b = V_DISPATCH(v) ? VARIANT_TRUE : VARIANT_FALSE;
180         break;
181     case VT_BOOL:
182         *b = V_BOOL(v);
183         break;
184     default:
185         FIXME("unimplemented for vt %d\n", V_VT(v));
186         return E_NOTIMPL;
187     }
188
189     return S_OK;
190 }
191
192 /* ECMA-262 3rd Edition    9.3 */
193 HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
194 {
195     switch(V_VT(v)) {
196     case VT_I4:
197     case VT_R8:
198         *ret = *v;
199         break;
200     default:
201         FIXME("unimplemented for vt %d\n", V_VT(v));
202         return E_NOTIMPL;
203     }
204
205     return S_OK;
206 }
207
208 /* ECMA-262 3rd Edition    9.8 */
209 HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
210 {
211     switch(V_VT(v)) {
212     case VT_BSTR:
213         *str = SysAllocString(V_BSTR(v));
214         return S_OK;
215
216     default:
217         FIXME("unsupported vt %d\n", V_VT(v));
218     }
219
220     return E_NOTIMPL;
221 }
222
223 /* ECMA-262 3rd Edition    9.9 */
224 HRESULT to_object(exec_ctx_t *ctx, VARIANT *v, IDispatch **disp)
225 {
226     switch(V_VT(v)) {
227     case VT_DISPATCH:
228         IDispatch_AddRef(V_DISPATCH(v));
229         *disp = V_DISPATCH(v);
230         break;
231     default:
232         FIXME("unsupported vt %d\n", V_VT(v));
233         return E_NOTIMPL;
234     }
235
236     return S_OK;
237 }