162fb8d0ff483ee5b3eaa50db556de2ca88495ee
[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 static Boolean stringIdentifierEqual(const void *value1, const void *value2)
33 {
34     return strcmp((const char *)value1, (const char *)value2) == 0;
35 }
36
37 static CFHashCode stringIdentifierHash (const void *value)
38 {
39     const char *key = (const char *)value;
40     unsigned int len = strlen(key);
41     unsigned int result = len;
42
43     if (len <= 16) {
44         unsigned cnt = len;
45         while (cnt--) result = result * 257 + *(unsigned char *)key++;
46     } else {
47         unsigned cnt;
48         for (cnt = 8; cnt > 0; cnt--) result = result * 257 + *(unsigned char *)key++;
49         key += (len - 16);
50         for (cnt = 8; cnt > 0; cnt--) result = result * 257 + *(unsigned char *)key++;
51     }
52     result += (result << (len & 31));
53
54     return result;
55 }
56
57 CFDictionaryKeyCallBacks stringIdentifierCallbacks = {
58     0,
59     NULL,
60     NULL,
61     NULL,
62     stringIdentifierEqual,
63     stringIdentifierHash
64 };
65
66 static CFMutableDictionaryRef stringIdentifierDictionary = 0;
67
68 static CFMutableDictionaryRef getStringIdentifierDictionary()
69 {
70     if (!stringIdentifierDictionary)
71         stringIdentifierDictionary = CFDictionaryCreateMutable(NULL, 0, &stringIdentifierCallbacks, NULL);
72     return stringIdentifierDictionary;
73 }
74
75 static Boolean intIdentifierEqual(const void *value1, const void *value2)
76 {
77     return value1 == value2;
78 }
79
80 static CFHashCode intIdentifierHash (const void *value)
81 {
82     return (CFHashCode)value;
83 }
84
85 CFDictionaryKeyCallBacks intIdentifierCallbacks = {
86     0,
87     NULL,
88     NULL,
89     NULL,
90     intIdentifierEqual,
91     intIdentifierHash
92 };
93
94 static CFMutableDictionaryRef intIdentifierDictionary = 0;
95
96 static CFMutableDictionaryRef getIntIdentifierDictionary()
97 {
98     if (!intIdentifierDictionary)
99         intIdentifierDictionary = CFDictionaryCreateMutable(NULL, 0, &intIdentifierCallbacks, NULL);
100     return intIdentifierDictionary;
101 }
102
103 NPIdentifier _NPN_GetStringIdentifier (const NPUTF8 *name)
104 {
105     assert (name);
106     
107     if (name) {
108         PrivateIdentifier *identifier = 0;
109         
110         identifier = (PrivateIdentifier *)CFDictionaryGetValue (getStringIdentifierDictionary(), (const void *)name);
111         if (identifier == 0) {
112             identifier = (PrivateIdentifier *)malloc (sizeof(PrivateIdentifier));
113             // We never release identifier names, so this dictionary will grow, as will
114             // the memory for the identifier name strings.
115             identifier->isString = true;
116             const char *identifierName = strdup (name);
117             identifier->value.string = identifierName;
118
119             CFDictionaryAddValue (getStringIdentifierDictionary(), identifierName, (const void *)identifier);
120         }
121         return (NPIdentifier)identifier;
122     }
123     
124     return 0;
125 }
126
127 void _NPN_GetStringIdentifiers (const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers)
128 {
129     assert (names);
130     assert (identifiers);
131     
132     if (names && identifiers) {
133         int i;
134         
135         for (i = 0; i < nameCount; i++) {
136             identifiers[i] = _NPN_GetStringIdentifier (names[i]);
137         }
138     }
139 }
140
141 NPIdentifier _NPN_GetIntIdentifier(int32_t intid)
142 {
143     PrivateIdentifier *identifier = 0;
144     
145     identifier = (PrivateIdentifier *)CFDictionaryGetValue (getIntIdentifierDictionary(), (const void *)intid);
146     if (identifier == 0) {
147         identifier = (PrivateIdentifier *)malloc (sizeof(PrivateIdentifier));
148         // We never release identifier names, so this dictionary will grow.
149         identifier->isString = false;
150         identifier->value.number = intid;
151
152         CFDictionaryAddValue (getIntIdentifierDictionary(), (const void *)intid, (const void *)identifier);
153     }
154     return (NPIdentifier)identifier;
155 }
156
157 bool _NPN_IdentifierIsString(NPIdentifier identifier)
158 {
159     PrivateIdentifier *i = (PrivateIdentifier *)identifier;
160     return i->isString;
161 }
162
163 NPUTF8 *_NPN_UTF8FromIdentifier (NPIdentifier identifier)
164 {
165     PrivateIdentifier *i = (PrivateIdentifier *)identifier;
166     if (!i->isString || !i->value.string)
167         return NULL;
168         
169     return (NPUTF8 *)strdup(i->value.string);
170 }
171
172 int32_t _NPN_IntFromIdentifier(NPIdentifier identifier)
173 {
174     PrivateIdentifier *i = (PrivateIdentifier *)identifier;
175     if (!i->isString)
176         return 0;
177     return i->value.number;
178 }
179
180 NPBool NPN_VariantIsVoid (const NPVariant *variant)
181 {
182     return variant->type == NPVariantType_Void;
183 }
184
185 NPBool NPN_VariantIsNull (const NPVariant *variant)
186 {
187     return variant->type == NPVariantType_Null;
188 }
189
190 NPBool NPN_VariantIsUndefined (const NPVariant *variant)
191 {
192     return variant->type == NPVariantType_Void;
193 }
194
195 NPBool NPN_VariantIsBool (const NPVariant *variant)
196 {
197     return variant->type == NPVariantType_Bool;
198 }
199
200 NPBool NPN_VariantIsInt32 (const NPVariant *variant)
201 {
202     return variant->type == NPVariantType_Int32;
203 }
204
205 NPBool NPN_VariantIsDouble (const NPVariant *variant)
206 {
207     return variant->type == NPVariantType_Double;
208 }
209
210 NPBool NPN_VariantIsString (const NPVariant *variant)
211 {
212     return variant->type == NPVariantType_String;
213 }
214
215 NPBool NPN_VariantIsObject (const NPVariant *variant)
216 {
217     return variant->type == NPVariantType_Object;
218 }
219
220 NPBool NPN_VariantToBool (const NPVariant *variant, NPBool *result)
221 {
222     if (variant->type != NPVariantType_Bool)
223         return false;
224         
225     *result = variant->value.boolValue;
226     
227     return true;
228 }
229
230 NPString NPN_VariantToString (const NPVariant *variant)
231 {
232     if (variant->type != NPVariantType_String) {
233         NPString emptyString = { 0, 0 };
234         return emptyString;
235     }
236             
237     return variant->value.stringValue;
238 }
239
240 NPBool NPN_VariantToInt32 (const NPVariant *variant, int32_t *result)
241 {
242     if (variant->type == NPVariantType_Int32)
243         *result = variant->value.intValue;
244     else if (variant->type == NPVariantType_Double)
245         *result = (int32_t)variant->value.doubleValue;
246     else
247         return false;
248     
249     return true;
250 }
251
252 NPBool NPN_VariantToDouble (const NPVariant *variant, double *result)
253 {
254     if (variant->type == NPVariantType_Int32)
255         *result = (double)variant->value.intValue;
256     else if (variant->type == NPVariantType_Double)
257         *result = variant->value.doubleValue;
258     else
259         return false;
260     
261     return true;
262 }
263
264 NPBool NPN_VariantToObject (const NPVariant *variant, NPObject **result)
265 {
266     if (variant->type != NPVariantType_Object)
267         return false;
268             
269     *result = variant->value.objectValue;
270     
271     return true;
272 }
273
274 void NPN_InitializeVariantAsVoid (NPVariant *variant)
275 {
276     variant->type = NPVariantType_Void;
277 }
278
279 void NPN_InitializeVariantAsNull (NPVariant *variant)
280 {
281     variant->type = NPVariantType_Null;
282 }
283
284 void NPN_InitializeVariantAsUndefined (NPVariant *variant)
285 {
286     variant->type = NPVariantType_Void;
287 }
288
289 void NPN_InitializeVariantWithBool (NPVariant *variant, NPBool value)
290 {
291     variant->type = NPVariantType_Bool;
292     variant->value.boolValue = value;
293 }
294
295 void NPN_InitializeVariantWithInt32 (NPVariant *variant, int32_t value)
296 {
297     variant->type = NPVariantType_Int32;
298     variant->value.intValue = value;
299 }
300
301 void NPN_InitializeVariantWithDouble (NPVariant *variant, double value)
302 {
303     variant->type = NPVariantType_Double;
304     variant->value.doubleValue = value;
305 }
306
307 void NPN_InitializeVariantWithString (NPVariant *variant, const NPString *value)
308 {
309     variant->type = NPVariantType_String;
310     variant->value.stringValue = *value;
311 }
312
313 void NPN_InitializeVariantWithStringCopy (NPVariant *variant, const NPString *value)
314 {
315     variant->type = NPVariantType_String;
316     variant->value.stringValue.UTF8Length = value->UTF8Length;
317     variant->value.stringValue.UTF8Characters = (NPUTF8 *)malloc(sizeof(NPUTF8) * value->UTF8Length);
318     memcpy ((void *)variant->value.stringValue.UTF8Characters, value->UTF8Characters, sizeof(NPUTF8) * value->UTF8Length);
319 }
320
321 void NPN_InitializeVariantWithObject (NPVariant *variant, NPObject *value)
322 {
323     variant->type = NPVariantType_Object;
324     variant->value.objectValue = _NPN_RetainObject (value);
325 }
326
327 void NPN_InitializeVariantWithVariant (NPVariant *destination, const NPVariant *source)
328 {
329     switch (source->type){
330         case NPVariantType_Void: {
331             NPN_InitializeVariantAsVoid (destination);
332             break;
333         }
334         case NPVariantType_Null: {
335             NPN_InitializeVariantAsNull (destination);
336             break;
337         }
338         case NPVariantType_Bool: {
339             NPN_InitializeVariantWithBool (destination, source->value.boolValue);
340             break;
341         }
342         case NPVariantType_Int32: {
343             NPN_InitializeVariantWithInt32 (destination, source->value.intValue);
344             break;
345         }
346         case NPVariantType_Double: {
347             NPN_InitializeVariantWithDouble (destination, source->value.doubleValue);
348             break;
349         }
350         case NPVariantType_String: {
351             NPN_InitializeVariantWithStringCopy (destination, &source->value.stringValue);
352             break;
353         }
354         case NPVariantType_Object: {
355             NPN_InitializeVariantWithObject (destination, source->value.objectValue);
356             break;
357         }
358         default: {
359             NPN_InitializeVariantAsUndefined (destination);
360             break;
361         }
362     }
363 }
364
365 void _NPN_ReleaseVariantValue (NPVariant *variant)
366 {
367     assert (variant);
368     
369     if (variant->type == NPVariantType_Object) {
370         _NPN_ReleaseObject (variant->value.objectValue);
371         variant->value.objectValue = 0;
372     }
373     else if (variant->type == NPVariantType_String) {
374         free ((void *)variant->value.stringValue.UTF8Characters);
375         variant->value.stringValue.UTF8Characters = 0;
376         variant->value.stringValue.UTF8Length = 0;
377     }
378     
379     variant->type = NPVariantType_Void;
380 }
381
382
383 NPObject *_NPN_CreateObject (NPP npp, NPClass *aClass)
384 {
385     assert (aClass);
386
387     if (aClass) {
388         NPObject *obj;
389         
390         if (aClass->allocate != NULL)
391             obj = aClass->allocate (npp, aClass);
392         else
393             obj = (NPObject *)malloc (sizeof(NPObject));
394             
395         obj->_class = aClass;
396         obj->referenceCount = 1;
397
398         return obj;
399     }
400     
401     return 0;
402 }
403
404
405 NPObject *_NPN_RetainObject (NPObject *obj)
406 {
407     assert (obj);
408
409     if (obj)
410         obj->referenceCount++;
411
412     return obj;
413 }
414
415
416 void _NPN_ReleaseObject (NPObject *obj)
417 {
418     assert (obj);
419     assert (obj->referenceCount >= 1);
420
421     if (obj && obj->referenceCount >= 1) {
422         obj->referenceCount--;
423                 
424         if (obj->referenceCount == 0) {
425             if (obj->_class->deallocate)
426                 obj->_class->deallocate (obj);
427             else
428                 free (obj);
429         }
430     }
431 }
432
433 void _NPN_SetExceptionWithUTF8 (NPObject *obj, const NPUTF8 *message, int32_t length)
434 {
435     assert (obj);
436     assert (message);
437  
438     if (obj && message) {
439         _NPN_SetException (obj, message);
440     }
441 }