JavaScriptCore:
[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)
167         return NULL;
168         
169     return (NPUTF8 *)i->value.string;
170 }
171
172 int32_t _NPN_IntFromIdentifier(NPIdentifier identifier)
173 {
174     // FIXME: Implement!
175     return 0;
176 }
177
178 NPBool NPN_VariantIsVoid (const NPVariant *variant)
179 {
180     return variant->type == NPVariantType_Void;
181 }
182
183 NPBool NPN_VariantIsNull (const NPVariant *variant)
184 {
185     return variant->type == NPVariantType_Null;
186 }
187
188 NPBool NPN_VariantIsUndefined (const NPVariant *variant)
189 {
190     return variant->type == NPVariantType_Void;
191 }
192
193 NPBool NPN_VariantIsBool (const NPVariant *variant)
194 {
195     return variant->type == NPVariantType_Bool;
196 }
197
198 NPBool NPN_VariantIsInt32 (const NPVariant *variant)
199 {
200     return variant->type == NPVariantType_Int32;
201 }
202
203 NPBool NPN_VariantIsDouble (const NPVariant *variant)
204 {
205     return variant->type == NPVariantType_Double;
206 }
207
208 NPBool NPN_VariantIsString (const NPVariant *variant)
209 {
210     return variant->type == NPVariantType_String;
211 }
212
213 NPBool NPN_VariantIsObject (const NPVariant *variant)
214 {
215     return variant->type == NPVariantType_Object;
216 }
217
218 NPBool NPN_VariantToBool (const NPVariant *variant, NPBool *result)
219 {
220     if (variant->type != NPVariantType_Bool)
221         return false;
222         
223     *result = variant->value.boolValue;
224     
225     return true;
226 }
227
228 NPString NPN_VariantToString (const NPVariant *variant)
229 {
230     if (variant->type != NPVariantType_String) {
231         NPString emptyString = { 0, 0 };
232         return emptyString;
233     }
234             
235     return variant->value.stringValue;
236 }
237
238 NPBool NPN_VariantToInt32 (const NPVariant *variant, int32_t *result)
239 {
240     if (variant->type == NPVariantType_Int32)
241         *result = variant->value.intValue;
242     else if (variant->type == NPVariantType_Double)
243         *result = (int32_t)variant->value.doubleValue;
244     else
245         return false;
246     
247     return true;
248 }
249
250 NPBool NPN_VariantToDouble (const NPVariant *variant, double *result)
251 {
252     if (variant->type == NPVariantType_Int32)
253         *result = (double)variant->value.intValue;
254     else if (variant->type == NPVariantType_Double)
255         *result = variant->value.doubleValue;
256     else
257         return false;
258     
259     return true;
260 }
261
262 NPBool NPN_VariantToObject (const NPVariant *variant, NPObject **result)
263 {
264     if (variant->type != NPVariantType_Object)
265         return false;
266             
267     *result = variant->value.objectValue;
268     
269     return true;
270 }
271
272 void NPN_InitializeVariantAsVoid (NPVariant *variant)
273 {
274     variant->type = NPVariantType_Void;
275 }
276
277 void NPN_InitializeVariantAsNull (NPVariant *variant)
278 {
279     variant->type = NPVariantType_Null;
280 }
281
282 void NPN_InitializeVariantAsUndefined (NPVariant *variant)
283 {
284     variant->type = NPVariantType_Void;
285 }
286
287 void NPN_InitializeVariantWithBool (NPVariant *variant, NPBool value)
288 {
289     variant->type = NPVariantType_Bool;
290     variant->value.boolValue = value;
291 }
292
293 void NPN_InitializeVariantWithInt32 (NPVariant *variant, int32_t value)
294 {
295     variant->type = NPVariantType_Int32;
296     variant->value.intValue = value;
297 }
298
299 void NPN_InitializeVariantWithDouble (NPVariant *variant, double value)
300 {
301     variant->type = NPVariantType_Double;
302     variant->value.doubleValue = value;
303 }
304
305 void NPN_InitializeVariantWithString (NPVariant *variant, const NPString *value)
306 {
307     variant->type = NPVariantType_String;
308     variant->value.stringValue = *value;
309 }
310
311 void NPN_InitializeVariantWithStringCopy (NPVariant *variant, const NPString *value)
312 {
313     variant->type = NPVariantType_String;
314     variant->value.stringValue.UTF8Length = value->UTF8Length;
315     variant->value.stringValue.UTF8Characters = (NPUTF8 *)malloc(sizeof(NPUTF8) * value->UTF8Length);
316     memcpy ((void *)variant->value.stringValue.UTF8Characters, value->UTF8Characters, sizeof(NPUTF8) * value->UTF8Length);
317 }
318
319 void NPN_InitializeVariantWithObject (NPVariant *variant, NPObject *value)
320 {
321     variant->type = NPVariantType_Object;
322     variant->value.objectValue = _NPN_RetainObject (value);
323 }
324
325 void NPN_InitializeVariantWithVariant (NPVariant *destination, const NPVariant *source)
326 {
327     switch (source->type){
328         case NPVariantType_Void: {
329             NPN_InitializeVariantAsVoid (destination);
330             break;
331         }
332         case NPVariantType_Null: {
333             NPN_InitializeVariantAsNull (destination);
334             break;
335         }
336         case NPVariantType_Bool: {
337             NPN_InitializeVariantWithBool (destination, source->value.boolValue);
338             break;
339         }
340         case NPVariantType_Int32: {
341             NPN_InitializeVariantWithInt32 (destination, source->value.intValue);
342             break;
343         }
344         case NPVariantType_Double: {
345             NPN_InitializeVariantWithDouble (destination, source->value.doubleValue);
346             break;
347         }
348         case NPVariantType_String: {
349             NPN_InitializeVariantWithStringCopy (destination, &source->value.stringValue);
350             break;
351         }
352         case NPVariantType_Object: {
353             NPN_InitializeVariantWithObject (destination, source->value.objectValue);
354             break;
355         }
356         default: {
357             NPN_InitializeVariantAsUndefined (destination);
358             break;
359         }
360     }
361 }
362
363 void _NPN_ReleaseVariantValue (NPVariant *variant)
364 {
365     assert (variant);
366     
367     if (variant->type == NPVariantType_Object) {
368         _NPN_ReleaseObject (variant->value.objectValue);
369         variant->value.objectValue = 0;
370     }
371     else if (variant->type == NPVariantType_String) {
372         free ((void *)variant->value.stringValue.UTF8Characters);
373         variant->value.stringValue.UTF8Characters = 0;
374         variant->value.stringValue.UTF8Length = 0;
375     }
376     
377     variant->type = NPVariantType_Void;
378 }
379
380
381 NPObject *_NPN_CreateObject (NPP npp, NPClass *aClass)
382 {
383     assert (aClass);
384
385     if (aClass) {
386         NPObject *obj;
387         
388         if (aClass->allocate != NULL)
389             obj = aClass->allocate (npp, aClass);
390         else
391             obj = (NPObject *)malloc (sizeof(NPObject));
392             
393         obj->_class = aClass;
394         obj->referenceCount = 1;
395
396         return obj;
397     }
398     
399     return 0;
400 }
401
402
403 NPObject *_NPN_RetainObject (NPObject *obj)
404 {
405     assert (obj);
406
407     if (obj)
408         obj->referenceCount++;
409
410     return obj;
411 }
412
413
414 void _NPN_ReleaseObject (NPObject *obj)
415 {
416     assert (obj);
417     assert (obj->referenceCount >= 1);
418
419     if (obj && obj->referenceCount >= 1) {
420         obj->referenceCount--;
421                 
422         if (obj->referenceCount == 0) {
423             if (obj->_class->deallocate)
424                 obj->_class->deallocate (obj);
425             else
426                 free (obj);
427         }
428     }
429 }
430
431 void _NPN_SetExceptionWithUTF8 (NPObject *obj, const NPUTF8 *message, int32_t length)
432 {
433     assert (obj);
434     assert (message);
435  
436     if (obj && message) {
437         NPString string;
438         string.UTF8Characters = message;
439         string.UTF8Length = length;
440         _NPN_SetException (obj, &string);
441     }
442 }