b902929bc0f6eece81c1823e6883e11ae979375f
[WebKit-https.git] / JavaScriptCore / bindings / objc / objc_utility.mm
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 <Foundation/Foundation.h>
26
27 #include <JavascriptCore/internal.h>
28
29 #include <objc_instance.h>
30 #include <objc_utility.h>
31
32 #include <runtime_array.h>
33 #include <runtime_object.h>
34 #include <runtime_root.h>
35
36 #include <WebScriptObjectPrivate.h>
37
38
39 using namespace KJS;
40 using namespace KJS::Bindings;
41
42 /*
43     The default name concatenates the components of the
44     ObjectiveC selector name and replaces ':' with '_'.  '_' characters
45     are escaped with an additional '$', i.e. '_' becomes "$_".  '$' are
46     also escaped, i.e.
47         ObjectiveC name         Default script name
48         moveTo::                move__
49         moveTo_                 moveTo$_
50         moveTo$_                moveTo$$$_
51     @result Returns the name to be used to represent the specificed selector in the
52 */
53 void KJS::Bindings::JSMethodNameToObjCMethodName(const char *name, char *buffer, unsigned int len)
54 {
55     const char *np = name;
56     char *bp;
57
58     if (strlen(name)*2+1 > len){
59         *buffer = 0;
60     }
61
62     bp = buffer;
63     while (*np) {
64         if (*np == '$') {
65             np++;
66             *bp++ = *np++;
67             continue;
68         }
69         
70         if (*np == '_') {
71             np++;
72             *bp++ = ':';
73         }
74         else
75             *bp++ = *np++;
76     }
77     *bp++ = 0;
78 }
79
80 /*
81
82     JavaScript to   ObjC
83     Number          coerced to char, short, int, long, float, double, or NSNumber, as appropriate
84     String          NSString
85     wrapper         id
86     Object          WebScriptObject
87     [], other       exception
88
89 */
90 ObjcValue KJS::Bindings::convertValueToObjcValue (KJS::ExecState *exec, const KJS::Value &value, ObjcValueType type)
91 {
92     ObjcValue result;
93     double d = 0;
94    
95     d = value.toNumber(exec);
96     switch (type){
97         case ObjcObjectType: {
98             const Bindings::RootObject *root = rootForInterpreter(exec->interpreter());
99             if (!root) {
100                 Bindings::RootObject *newRoot = new KJS::Bindings::RootObject(0);
101                 newRoot->setInterpreter (exec->interpreter());
102                 root = newRoot;
103             }
104             result.objectValue = [WebScriptObject _convertValueToObjcValue:value root:root];
105         }
106         break;
107         
108         
109         case ObjcCharType: {
110             result.charValue = (char)d;
111         }
112         break;
113
114         case ObjcShortType: {
115             result.shortValue = (short)d;
116         }
117         break;
118
119         case ObjcIntType: {
120             result.intValue = (int)d;
121         }
122         break;
123
124         case ObjcLongType: {
125             result.longValue = (long)d;
126         }
127         break;
128
129         case ObjcFloatType: {
130             result.floatValue = (float)d;
131         }
132         break;
133
134         case ObjcDoubleType: {
135             result.doubleValue = (double)d;
136         }
137         break;
138             
139         break;
140
141         case ObjcVoidType: {
142             bzero (&result, sizeof(ObjcValue));
143         }
144         break;
145
146         case ObjcInvalidType:
147         default:
148         {
149             // FIXME:  throw an exception
150         }
151         break;
152     }
153     return result;
154 }
155
156 /*
157
158     ObjC      to    JavaScript
159     char            Number
160     short
161     int
162     long
163     float
164     double
165     NSNumber        Number
166     NSString        String
167     NSArray         Array
168     id              Object wrapper
169     other           should not happen
170
171 */
172 Value KJS::Bindings::convertObjcValueToValue (KJS::ExecState *exec, void *buffer, ObjcValueType type)
173 {
174     Value aValue;
175
176     switch (type) {
177         case ObjcObjectType:
178             {
179                 ObjectStructPtr *obj = (ObjectStructPtr *)buffer;
180
181                 /*
182                     NSNumber to Number
183                     NSString to String
184                     NSArray  to Array
185                     id       to Object wrapper
186                 */
187                 if ([*obj isKindOfClass:[NSString class]]){
188                     NSString *string = (NSString *)*obj;
189                     unichar *chars;
190                     unsigned int length = [string length];
191                     chars = (unichar *)malloc(sizeof(unichar)*length);
192                     [string getCharacters:chars];
193                     UString u((const KJS::UChar*)chars, length);
194                     aValue = String (u);
195                     free((void *)chars);
196                 }
197                 else if ([*obj isKindOfClass:[NSNumber class]]) {
198                     aValue = Number([*obj doubleValue]);
199                 }
200                 else if ([*obj isKindOfClass:[NSArray class]]) {
201                     aValue = Object(new RuntimeArrayImp(exec, new ObjcArray (*obj)));
202                 }
203                 else if ([*obj isKindOfClass:[WebScriptObject class]]) {
204                     WebScriptObject *jsobject = (WebScriptObject *)*obj;
205                     aValue = Object([jsobject _imp]);
206                 }
207                 else if ((CFBooleanRef)*obj == kCFBooleanTrue) {
208                     aValue = Boolean(true);
209                 }
210                 else if ((CFBooleanRef)*obj == kCFBooleanFalse) {
211                     aValue = Boolean(false);
212                 }
213                 else if (*obj == 0) {
214                     return Undefined();
215                 }
216                 else {
217                     aValue = Object(new RuntimeObjectImp(new ObjcInstance (*obj)));
218                 }
219             }
220             break;
221         case ObjcCharType:
222             {
223                 char *objcVal = (char *)buffer;
224                 aValue = Number ((short)*objcVal);
225             }
226             break;
227         case ObjcShortType:
228             {
229                 short *objcVal = (short *)buffer;
230                 aValue = Number ((short)*objcVal);
231             }
232             break;
233         case ObjcIntType:
234             {
235                 int *objcVal = (int *)buffer;
236                 aValue = Number ((int)*objcVal);
237             }
238             break;
239         case ObjcLongType:
240             {
241                 long *objcVal = (long *)buffer;
242                 aValue = Number ((long)*objcVal);
243             }
244             break;
245         case ObjcFloatType:
246             {
247                 float *objcVal = (float *)buffer;
248                 aValue = Number ((float)*objcVal);
249             }
250             break;
251         case ObjcDoubleType:
252             {
253                 double *objcVal = (double *)buffer;
254                 aValue = Number ((double)*objcVal);
255             }
256             break;
257         default:
258             // Should never get here.  Argument types are filtered (and
259             // the assert above should have fired in the impossible case
260             // of an invalid type anyway).
261             fprintf (stderr, "%s:  invalid type (%d)\n", __PRETTY_FUNCTION__, (int)type);
262             assert (true);
263     }
264     
265     return aValue;
266 }
267
268
269 ObjcValueType KJS::Bindings::objcValueTypeForType (const char *type)
270 {
271     int typeLength = strlen(type);
272     ObjcValueType objcValueType = ObjcInvalidType;
273     
274     if (typeLength == 1) {
275         char typeChar = type[0];
276         switch (typeChar){
277             case _C_ID: {
278                 objcValueType = ObjcObjectType;
279             }
280             break;
281             case _C_CHR: {
282                 objcValueType = ObjcCharType;
283             }
284             break;
285             case _C_SHT: {
286                 objcValueType = ObjcShortType;
287             }
288             break;
289             case _C_INT: {
290                 objcValueType = ObjcIntType;
291             }
292             break;
293             case _C_LNG: {
294                 objcValueType = ObjcLongType;
295             }
296             break;
297             case _C_FLT: {
298                 objcValueType = ObjcFloatType;
299             }
300             break;
301             case _C_DBL: {
302                 objcValueType = ObjcDoubleType;
303             }
304             break;
305             case _C_VOID: {
306                 objcValueType = ObjcVoidType;
307             }
308             break;
309         }
310     }
311     return objcValueType;
312 }
313
314