Reviewed by Geoff.
[WebKit-https.git] / JavaScriptCore / bindings / npruntime.cpp
1 /*
2  * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25 #include <CoreFoundation/CoreFoundation.h>
26
27 #include <npruntime.h>
28 #include <c_utility.h>
29
30 #include <JavaScriptCore/npruntime_impl.h>
31
32 using namespace KJS::Bindings;
33
34 static Boolean stringIdentifierEqual(const void *value1, const void *value2)
35 {
36     return strcmp((const char *)value1, (const char *)value2) == 0;
37 }
38
39 static CFHashCode stringIdentifierHash (const void *value)
40 {
41     const char *key = (const char *)value;
42     unsigned int len = strlen(key);
43     unsigned int result = len;
44
45     if (len <= 16) {
46         unsigned cnt = len;
47         while (cnt--) result = result * 257 + *(unsigned char *)key++;
48     } else {
49         unsigned cnt;
50         for (cnt = 8; cnt > 0; cnt--) result = result * 257 + *(unsigned char *)key++;
51         key += (len - 16);
52         for (cnt = 8; cnt > 0; cnt--) result = result * 257 + *(unsigned char *)key++;
53     }
54     result += (result << (len & 31));
55
56     return result;
57 }
58
59 static CFDictionaryKeyCallBacks stringIdentifierCallbacks = {
60     0,
61     NULL,
62     NULL,
63     NULL,
64     stringIdentifierEqual,
65     stringIdentifierHash
66 };
67
68 static CFMutableDictionaryRef stringIdentifierDictionary = 0;
69
70 static CFMutableDictionaryRef getStringIdentifierDictionary()
71 {
72     if (!stringIdentifierDictionary)
73         stringIdentifierDictionary = CFDictionaryCreateMutable(NULL, 0, &stringIdentifierCallbacks, NULL);
74     return stringIdentifierDictionary;
75 }
76
77 static Boolean intIdentifierEqual(const void *value1, const void *value2)
78 {
79     return value1 == value2;
80 }
81
82 static CFHashCode intIdentifierHash (const void *value)
83 {
84     return (CFHashCode)value;
85 }
86
87 static CFDictionaryKeyCallBacks intIdentifierCallbacks = {
88     0,
89     NULL,
90     NULL,
91     NULL,
92     intIdentifierEqual,
93     intIdentifierHash
94 };
95
96 static CFMutableDictionaryRef intIdentifierDictionary = 0;
97
98 static CFMutableDictionaryRef getIntIdentifierDictionary()
99 {
100     if (!intIdentifierDictionary)
101         intIdentifierDictionary = CFDictionaryCreateMutable(NULL, 0, &intIdentifierCallbacks, NULL);
102     return intIdentifierDictionary;
103 }
104
105 NPIdentifier _NPN_GetStringIdentifier (const NPUTF8 *name)
106 {
107     assert (name);
108     
109     if (name) {
110         PrivateIdentifier *identifier = 0;
111         
112         identifier = (PrivateIdentifier *)CFDictionaryGetValue (getStringIdentifierDictionary(), (const void *)name);
113         if (identifier == 0) {
114             identifier = (PrivateIdentifier *)malloc (sizeof(PrivateIdentifier));
115             // We never release identifier names, so this dictionary will grow, as will
116             // the memory for the identifier name strings.
117             identifier->isString = true;
118             const char *identifierName = strdup (name);
119             identifier->value.string = identifierName;
120
121             CFDictionaryAddValue (getStringIdentifierDictionary(), identifierName, (const void *)identifier);
122         }
123         return (NPIdentifier)identifier;
124     }
125     
126     return 0;
127 }
128
129 void _NPN_GetStringIdentifiers (const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers)
130 {
131     assert (names);
132     assert (identifiers);
133     
134     if (names && identifiers) {
135         int i;
136         
137         for (i = 0; i < nameCount; i++) {
138             identifiers[i] = _NPN_GetStringIdentifier (names[i]);
139         }
140     }
141 }
142
143 NPIdentifier _NPN_GetIntIdentifier(int32_t intid)
144 {
145     PrivateIdentifier *identifier = 0;
146     
147     identifier = (PrivateIdentifier *)CFDictionaryGetValue (getIntIdentifierDictionary(), (const void *)intid);
148     if (identifier == 0) {
149         identifier = (PrivateIdentifier *)malloc (sizeof(PrivateIdentifier));
150         // We never release identifier names, so this dictionary will grow.
151         identifier->isString = false;
152         identifier->value.number = intid;
153
154         CFDictionaryAddValue (getIntIdentifierDictionary(), (const void *)intid, (const void *)identifier);
155     }
156     return (NPIdentifier)identifier;
157 }
158
159 bool _NPN_IdentifierIsString(NPIdentifier identifier)
160 {
161     PrivateIdentifier *i = (PrivateIdentifier *)identifier;
162     return i->isString;
163 }
164
165 NPUTF8 *_NPN_UTF8FromIdentifier (NPIdentifier identifier)
166 {
167     PrivateIdentifier *i = (PrivateIdentifier *)identifier;
168     if (!i->isString || !i->value.string)
169         return NULL;
170         
171     return (NPUTF8 *)strdup(i->value.string);
172 }
173
174 int32_t _NPN_IntFromIdentifier(NPIdentifier identifier)
175 {
176     PrivateIdentifier *i = (PrivateIdentifier *)identifier;
177     if (!i->isString)
178         return 0;
179     return i->value.number;
180 }
181
182 NPBool NPN_VariantIsVoid (const NPVariant *variant)
183 {
184     return variant->type == NPVariantType_Void;
185 }
186
187 NPBool NPN_VariantIsNull (const NPVariant *variant)
188 {
189     return variant->type == NPVariantType_Null;
190 }
191
192 NPBool NPN_VariantIsUndefined (const NPVariant *variant)
193 {
194     return variant->type == NPVariantType_Void;
195 }
196
197 NPBool NPN_VariantIsBool (const NPVariant *variant)
198 {
199     return variant->type == NPVariantType_Bool;
200 }
201
202 NPBool NPN_VariantIsInt32 (const NPVariant *variant)
203 {
204     return variant->type == NPVariantType_Int32;
205 }
206
207 NPBool NPN_VariantIsDouble (const NPVariant *variant)
208 {
209     return variant->type == NPVariantType_Double;
210 }
211
212 NPBool NPN_VariantIsString (const NPVariant *variant)
213 {
214     return variant->type == NPVariantType_String;
215 }
216
217 NPBool NPN_VariantIsObject (const NPVariant *variant)
218 {
219     return variant->type == NPVariantType_Object;
220 }
221
222 NPBool NPN_VariantToBool (const NPVariant *variant, NPBool *result)
223 {
224     if (variant->type != NPVariantType_Bool)
225         return false;
226         
227     *result = variant->value.boolValue;
228     
229     return true;
230 }
231
232 NPString NPN_VariantToString (const NPVariant *variant)
233 {
234     if (variant->type != NPVariantType_String) {
235         NPString emptyString = { 0, 0 };
236         return emptyString;
237     }
238             
239     return variant->value.stringValue;
240 }
241
242 NPBool NPN_VariantToInt32 (const NPVariant *variant, int32_t *result)
243 {
244     if (variant->type == NPVariantType_Int32)
245         *result = variant->value.intValue;
246     else if (variant->type == NPVariantType_Double)
247         *result = (int32_t)variant->value.doubleValue;
248     else
249         return false;
250     
251     return true;
252 }
253
254 NPBool NPN_VariantToDouble (const NPVariant *variant, double *result)
255 {
256     if (variant->type == NPVariantType_Int32)
257         *result = (double)variant->value.intValue;
258     else if (variant->type == NPVariantType_Double)
259         *result = variant->value.doubleValue;
260     else
261         return false;
262     
263     return true;
264 }
265
266 NPBool NPN_VariantToObject (const NPVariant *variant, NPObject **result)
267 {
268     if (variant->type != NPVariantType_Object)
269         return false;
270             
271     *result = variant->value.objectValue;
272     
273     return true;
274 }
275
276 void NPN_InitializeVariantAsVoid (NPVariant *variant)
277 {
278     variant->type = NPVariantType_Void;
279 }
280
281 void NPN_InitializeVariantAsNull (NPVariant *variant)
282 {
283     variant->type = NPVariantType_Null;
284 }
285
286 void NPN_InitializeVariantAsUndefined (NPVariant *variant)
287 {
288     variant->type = NPVariantType_Void;
289 }
290
291 void NPN_InitializeVariantWithBool (NPVariant *variant, NPBool value)
292 {
293     variant->type = NPVariantType_Bool;
294     variant->value.boolValue = value;
295 }
296
297 void NPN_InitializeVariantWithInt32 (NPVariant *variant, int32_t value)
298 {
299     variant->type = NPVariantType_Int32;
300     variant->value.intValue = value;
301 }
302
303 void NPN_InitializeVariantWithDouble (NPVariant *variant, double value)
304 {
305     variant->type = NPVariantType_Double;
306     variant->value.doubleValue = value;
307 }
308
309 void NPN_InitializeVariantWithString (NPVariant *variant, const NPString *value)
310 {
311     variant->type = NPVariantType_String;
312     variant->value.stringValue = *value;
313 }
314
315 void NPN_InitializeVariantWithStringCopy (NPVariant *variant, const NPString *value)
316 {
317     variant->type = NPVariantType_String;
318     variant->value.stringValue.UTF8Length = value->UTF8Length;
319     variant->value.stringValue.UTF8Characters = (NPUTF8 *)malloc(sizeof(NPUTF8) * value->UTF8Length);
320     memcpy ((void *)variant->value.stringValue.UTF8Characters, value->UTF8Characters, sizeof(NPUTF8) * value->UTF8Length);
321 }
322
323 void NPN_InitializeVariantWithObject (NPVariant *variant, NPObject *value)
324 {
325     variant->type = NPVariantType_Object;
326     variant->value.objectValue = _NPN_RetainObject (value);
327 }
328
329 void NPN_InitializeVariantWithVariant (NPVariant *destination, const NPVariant *source)
330 {
331     switch (source->type){
332         case NPVariantType_Void: {
333             NPN_InitializeVariantAsVoid (destination);
334             break;
335         }
336         case NPVariantType_Null: {
337             NPN_InitializeVariantAsNull (destination);
338             break;
339         }
340         case NPVariantType_Bool: {
341             NPN_InitializeVariantWithBool (destination, source->value.boolValue);
342             break;
343         }
344         case NPVariantType_Int32: {
345             NPN_InitializeVariantWithInt32 (destination, source->value.intValue);
346             break;
347         }
348         case NPVariantType_Double: {
349             NPN_InitializeVariantWithDouble (destination, source->value.doubleValue);
350             break;
351         }
352         case NPVariantType_String: {
353             NPN_InitializeVariantWithStringCopy (destination, &source->value.stringValue);
354             break;
355         }
356         case NPVariantType_Object: {
357             NPN_InitializeVariantWithObject (destination, source->value.objectValue);
358             break;
359         }
360         default: {
361             NPN_InitializeVariantAsUndefined (destination);
362             break;
363         }
364     }
365 }
366
367 void _NPN_ReleaseVariantValue (NPVariant *variant)
368 {
369     assert (variant);
370     
371     if (variant->type == NPVariantType_Object) {
372         _NPN_ReleaseObject (variant->value.objectValue);
373         variant->value.objectValue = 0;
374     }
375     else if (variant->type == NPVariantType_String) {
376         free ((void *)variant->value.stringValue.UTF8Characters);
377         variant->value.stringValue.UTF8Characters = 0;
378         variant->value.stringValue.UTF8Length = 0;
379     }
380     
381     variant->type = NPVariantType_Void;
382 }
383
384
385 NPObject *_NPN_CreateObject (NPP npp, NPClass *aClass)
386 {
387     assert (aClass);
388
389     if (aClass) {
390         NPObject *obj;
391         
392         if (aClass->allocate != NULL)
393             obj = aClass->allocate (npp, aClass);
394         else
395             obj = (NPObject *)malloc (sizeof(NPObject));
396             
397         obj->_class = aClass;
398         obj->referenceCount = 1;
399
400         return obj;
401     }
402     
403     return 0;
404 }
405
406
407 NPObject *_NPN_RetainObject (NPObject *obj)
408 {
409     assert (obj);
410
411     if (obj)
412         obj->referenceCount++;
413
414     return obj;
415 }
416
417
418 void _NPN_ReleaseObject (NPObject *obj)
419 {
420     assert (obj);
421     assert (obj->referenceCount >= 1);
422
423     if (obj && obj->referenceCount >= 1) {
424         obj->referenceCount--;
425                 
426         if (obj->referenceCount == 0) {
427             if (obj->_class->deallocate)
428                 obj->_class->deallocate (obj);
429             else
430                 free (obj);
431         }
432     }
433 }