jscript: Added logical negation implementation.
[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.2 */
137 HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b)
138 {
139     switch(V_VT(v)) {
140     case VT_EMPTY:
141     case VT_NULL:
142         *b = VARIANT_FALSE;
143         break;
144     case VT_I4:
145         *b = V_I4(v) ? VARIANT_TRUE : VARIANT_FALSE;
146         break;
147     case VT_R8:
148         *b = V_R8(v) ? VARIANT_TRUE : VARIANT_FALSE;
149         break;
150     case VT_BSTR:
151         *b = V_BSTR(v) && *V_BSTR(v) ? VARIANT_TRUE : VARIANT_FALSE;
152         break;
153     case VT_DISPATCH:
154         *b = V_DISPATCH(v) ? VARIANT_TRUE : VARIANT_FALSE;
155         break;
156     case VT_BOOL:
157         *b = V_BOOL(v);
158         break;
159     default:
160         FIXME("unimplemented for vt %d\n", V_VT(v));
161         return E_NOTIMPL;
162     }
163
164     return S_OK;
165 }