- Rolled out HashMap implementation of NPRuntime, at least temporarily.
[WebKit-https.git] / JavaScriptCore / bindings / npruntime.cpp
1 /*
2  * Copyright (C) 2004, 2006 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
26 #include "config.h"
27 #include "npruntime.h"
28 #include "npruntime_impl.h"
29 #include "npruntime_priv.h"
30
31 #include "c_utility.h"
32 #include <CoreFoundation/CoreFoundation.h>
33
34 // FIXME: Use HashMap instead of CFDictionary for better performance and portability.
35
36 using namespace KJS::Bindings;
37
38 static Boolean stringIdentifierEqual(const void* value1, const void* value2)
39 {
40     return strcmp((const char*)value1, (const char*)value2) == 0;
41 }
42
43 static CFHashCode stringIdentifierHash(const void* value)
44 {
45     const unsigned char* key = (const unsigned char*)value;
46     unsigned len = strlen((const char*)key);
47     unsigned result = len;
48
49     if (len <= 16) {
50         unsigned cnt = len;
51         while (cnt--)
52             result = result * 257 + *key++;
53     } else {
54         unsigned cnt;
55         for (cnt = 8; cnt > 0; cnt--)
56             result = result * 257 + *key++;
57         key += (len - 16);
58         for (cnt = 8; cnt > 0; cnt--)
59             result = result * 257 + *key++;
60     }
61     result += (result << (len & 31));
62
63     return result;
64 }
65
66 static CFMutableDictionaryRef getStringIdentifierDictionary()
67 {
68     static CFMutableDictionaryRef stringIdentifierDictionary = 0;
69     if (!stringIdentifierDictionary) {
70         CFDictionaryKeyCallBacks stringIdentifierCallbacks = { 0, NULL, NULL, NULL, stringIdentifierEqual, stringIdentifierHash };
71         stringIdentifierDictionary = CFDictionaryCreateMutable(NULL, 0, &stringIdentifierCallbacks, NULL);
72     }
73     return stringIdentifierDictionary;
74 }
75
76 static CFMutableDictionaryRef getIntIdentifierDictionary()
77 {
78     static CFMutableDictionaryRef intIdentifierDictionary = 0;
79     if (!intIdentifierDictionary)
80         intIdentifierDictionary = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
81     return intIdentifierDictionary;
82 }
83
84 NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name)
85 {
86     assert(name);
87     
88     if (name) {
89         PrivateIdentifier* identifier = 0;
90         
91         identifier = (PrivateIdentifier*)CFDictionaryGetValue(getStringIdentifierDictionary(), name);
92         if (identifier == 0) {
93             identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
94             // We never release identifier names, so this dictionary will grow, as will
95             // the memory for the identifier name strings.
96             identifier->isString = true;
97             const char* identifierName = strdup(name);
98             identifier->value.string = identifierName;
99
100             CFDictionaryAddValue(getStringIdentifierDictionary(), identifierName, identifier);
101         }
102         return (NPIdentifier)identifier;
103     }
104     
105     return 0;
106 }
107
108 void _NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers)
109 {
110     assert(names);
111     assert(identifiers);
112     
113     if (names && identifiers)
114         for (int i = 0; i < nameCount; i++)
115             identifiers[i] = _NPN_GetStringIdentifier(names[i]);
116 }
117
118 NPIdentifier _NPN_GetIntIdentifier(int32_t intid)
119 {
120     PrivateIdentifier* identifier = 0;
121     
122     identifier = (PrivateIdentifier*)CFDictionaryGetValue(getIntIdentifierDictionary(), (const void*)intid);
123     if (identifier == 0) {
124         identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
125         // We never release identifier names, so this dictionary will grow.
126         identifier->isString = false;
127         identifier->value.number = intid;
128
129         CFDictionaryAddValue(getIntIdentifierDictionary(), (const void*)intid, identifier);
130     }
131     return (NPIdentifier)identifier;
132 }
133
134 bool _NPN_IdentifierIsString(NPIdentifier identifier)
135 {
136     PrivateIdentifier* i = (PrivateIdentifier*)identifier;
137     return i->isString;
138 }
139
140 NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier identifier)
141 {
142     PrivateIdentifier* i = (PrivateIdentifier*)identifier;
143     if (!i->isString || !i->value.string)
144         return NULL;
145         
146     return (NPUTF8 *)strdup(i->value.string);
147 }
148
149 int32_t _NPN_IntFromIdentifier(NPIdentifier identifier)
150 {
151     PrivateIdentifier* i = (PrivateIdentifier*)identifier;
152     if (!i->isString)
153         return 0;
154     return i->value.number;
155 }
156
157 void NPN_InitializeVariantWithStringCopy(NPVariant* variant, const NPString* value)
158 {
159     variant->type = NPVariantType_String;
160     variant->value.stringValue.UTF8Length = value->UTF8Length;
161     variant->value.stringValue.UTF8Characters = (NPUTF8 *)malloc(sizeof(NPUTF8) * value->UTF8Length);
162     memcpy((void*)variant->value.stringValue.UTF8Characters, value->UTF8Characters, sizeof(NPUTF8) * value->UTF8Length);
163 }
164
165 void _NPN_ReleaseVariantValue(NPVariant* variant)
166 {
167     assert(variant);
168
169     if (variant->type == NPVariantType_Object) {
170         _NPN_ReleaseObject(variant->value.objectValue);
171         variant->value.objectValue = 0;
172     } else if (variant->type == NPVariantType_String) {
173         free((void*)variant->value.stringValue.UTF8Characters);
174         variant->value.stringValue.UTF8Characters = 0;
175         variant->value.stringValue.UTF8Length = 0;
176     }
177
178     variant->type = NPVariantType_Void;
179 }
180
181 NPObject *_NPN_CreateObject(NPP npp, NPClass* aClass)
182 {
183     assert(aClass);
184
185     if (aClass) {
186         NPObject* obj;
187         if (aClass->allocate != NULL)
188             obj = aClass->allocate(npp, aClass);
189         else
190             obj = (NPObject*)malloc(sizeof(NPObject));
191
192         obj->_class = aClass;
193         obj->referenceCount = 1;
194
195         return obj;
196     }
197
198     return 0;
199 }
200
201 NPObject* _NPN_RetainObject(NPObject* obj)
202 {
203     assert(obj);
204
205     if (obj)
206         obj->referenceCount++;
207
208     return obj;
209 }
210
211 void _NPN_ReleaseObject(NPObject* obj)
212 {
213     assert(obj);
214     assert(obj->referenceCount >= 1);
215
216     if (obj && obj->referenceCount >= 1) {
217         if (--obj->referenceCount == 0)
218             _NPN_DeallocateObject(obj);
219     }
220 }
221
222 void _NPN_DeallocateObject(NPObject *obj)
223 {
224     assert(obj);
225
226     if (obj) {
227         if (obj->_class->deallocate)
228             obj->_class->deallocate(obj);
229         else
230             free(obj);
231     }
232 }