migrate substitution keywords to SVN
[reactos.git] / reactos / lib / kjs / src / utils.c
1 /*
2 * General utilites.
3 * Copyright (c) 1998 New Generation Software (NGS) Oy
4 *
5 * Author: Markku Rossi <mtr@ngs.fi>
6 */
7
8 /*
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * MA 02111-1307, USA
23 */
24
25 /*
26 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/src/utils.c,v $
27 * $Id$
28 */
29
30 #include "jsint.h"
31
32 /*
33 * Global variables.
34 */
35
36 unsigned char js_latin1_tolower[256] =
37 {
38 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
39 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
40 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
41 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
42 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
43 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
44 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
45 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
46 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
47 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
48 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
49 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
50 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
51 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
52 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
53 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
54 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
55 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
56 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
57 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
58 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
59 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
60 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
61 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
62 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0x61, 0xe7,
63 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
64 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7,
65 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf,
66 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
67 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
68 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
69 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
70 };
71
72 unsigned char js_latin1_toupper[256] =
73 {
74 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
75 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
76 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
77 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
78 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
79 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
80 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
81 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
82 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
83 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
84 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
85 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
86 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
87 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
88 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
89 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
90 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
91 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
92 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
93 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
94 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
95 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
96 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
97 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
98 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
99 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
100 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
101 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
102 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xe6, 0xc7,
103 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
104 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7,
105 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff,
106 };
107
108
109 /*
110 * Global functions.
111 */
112
113 void
114 js_vm_to_primitive (JSVirtualMachine *vm, const JSNode *n,
115 JSNode *result_return, JSNodeType preferred_type)
116 {
117 JSNode args;
118
119 switch (n->type)
120 {
121 case JS_UNDEFINED:
122 case JS_NULL:
123 case JS_BOOLEAN:
124 case JS_INTEGER:
125 case JS_FLOAT:
126 case JS_NAN:
127 case JS_STRING:
128 JS_COPY (result_return, n);
129 break;
130
131 case JS_OBJECT:
132 if (preferred_type == JS_STRING)
133 {
134 if (js_vm_call_method (vm, (JSNode *) n, "toString", 0, &args)
135 && JS_IS_PRIMITIVE_VALUE (&vm->exec_result))
136 JS_COPY (result_return, &vm->exec_result);
137 else if (js_vm_call_method (vm, (JSNode *) n, "valueOf", 0, &args)
138 && JS_IS_PRIMITIVE_VALUE (&vm->exec_result))
139 JS_COPY (result_return, &vm->exec_result);
140 else
141 {
142 sprintf (vm->error, "ToPrimitive(): couldn't convert");
143 js_vm_error (vm);
144 }
145 }
146 else
147 {
148 /* It must be, or it defaults to NUMBER. */
149 if (js_vm_call_method (vm, (JSNode *) n, "valueOf", 0, &args)
150 && JS_IS_PRIMITIVE_VALUE (&vm->exec_result))
151 JS_COPY (result_return, &vm->exec_result);
152 else
153 js_vm_to_string (vm, n, result_return);
154 }
155 break;
156
157 case JS_BUILTIN:
158 /* XXX ToPrimitive() for built-ins. */
159 sprintf (vm->error, "ToPrimitive(): not implemented yet for built-ins");
160 js_vm_error (vm);
161 break;
162
163 case JS_ARRAY:
164 case JS_SYMBOL:
165 case JS_FUNC:
166 case JS_IPTR:
167 default:
168 sprintf (vm->error, "ToPrimitive(): couldn't convert (%d)", n->type);
169 js_vm_error (vm);
170 break;
171 }
172 }
173
174
175 void
176 js_vm_to_string (JSVirtualMachine *vm, const JSNode *n, JSNode *result_return)
177 {
178 const char *tostring;
179 JSNode args;
180 JSNode *nnoconst = (JSNode *) n; /* toString methods behave `constantly'
181 so no panic here. */
182
183 /* Create empty arguments. */
184 args.type = JS_INTEGER;
185 args.u.vinteger = 0;
186
187 switch (n->type)
188 {
189 case JS_UNDEFINED:
190 tostring = "undefined";
191 break;
192
193 case JS_NULL:
194 tostring = "null";
195 break;
196
197 case JS_BOOLEAN:
198 case JS_INTEGER:
199 case JS_FLOAT:
200 case JS_NAN:
201 case JS_STRING:
202 case JS_ARRAY:
203 (void) (*vm->prim[n->type]->method_proc) (vm, vm->prim[n->type],
204 nnoconst, vm->syms.s_toString,
205 result_return, &args);
206 return;
207 break;
208
209 case JS_OBJECT:
210 /* Try to call object's toString() method. */
211 if (js_vm_call_method (vm, (JSNode *) n, "toString", 0, &args)
212 && vm->exec_result.type == JS_STRING)
213 {
214 JS_COPY (result_return, &vm->exec_result);
215 return;
216 }
217
218 /* No match. */
219 tostring = "object";
220 break;
221
222 case JS_SYMBOL:
223 tostring = js_vm_symname (vm, n->u.vsymbol);
224 break;
225
226 case JS_BUILTIN:
227 if (n->u.vbuiltin->info->method_proc)
228 if ((*n->u.vbuiltin->info->method_proc) (
229 vm,
230 n->u.vbuiltin->info,
231 n->u.vbuiltin->instance_context,
232 vm->syms.s_toString, result_return,
233 &args)
234 == JS_PROPERTY_FOUND)
235 return;
236
237 /* Builtin didn't answer toString(). Let's use our default. */
238 tostring = "builtin";
239 break;
240
241 case JS_FUNC:
242 tostring = "function";
243 break;
244
245 case JS_IPTR:
246 tostring = "pointer";
247 break;
248
249 default:
250 tostring = "??? unknown type in js_vm_to_string() ???";
251 break;
252 }
253
254 js_vm_make_static_string (vm, result_return, tostring, strlen (tostring));
255 }
256
257
258 void
259 js_vm_to_number (JSVirtualMachine *vm, const JSNode *n, JSNode *result_return)
260 {
261 char *cp, *end;
262
263 switch (n->type)
264 {
265 case JS_UNDEFINED:
266 result_return->type = JS_NAN;
267 break;
268
269 case JS_NULL:
270 result_return->type = JS_INTEGER;
271 result_return->u.vinteger = 0;
272 break;
273
274 case JS_BOOLEAN:
275 result_return->type = JS_INTEGER;
276 result_return->u.vinteger = n->u.vboolean ? 1 : 0;
277 break;
278
279 case JS_INTEGER:
280 case JS_FLOAT:
281 case JS_NAN:
282 JS_COPY (result_return, n);
283 break;
284
285 case JS_STRING:
286 cp = js_string_to_c_string (vm, n);
287 result_return->u.vinteger = strtol (cp, &end, 10);
288
289 if (cp == end)
290 {
291 int i;
292
293 /* It failed. Check the `Infinity'. */
294
295 for (i = 0; cp[i] && JS_IS_STR_WHITE_SPACE_CHAR (cp[i]); i++)
296 ;
297
298 if (cp[i] && memcmp (cp + i, "Infinity", 8) == 0)
299 JS_MAKE_POSITIVE_INFINITY (result_return);
300 else
301 result_return->type = JS_NAN;
302 }
303 else
304 {
305 if (*end == '.' || *end == 'e' || *end == 'E')
306 {
307 /* It is a float number. */
308 result_return->u.vfloat = strtod (cp, &end);
309 if (cp == end)
310 /* Couldn't parse. */
311 result_return->type = JS_NAN;
312 else
313 /* Success. */
314 result_return->type = JS_FLOAT;
315 }
316 else
317 {
318 /* It is an integer. */
319 result_return->type = JS_INTEGER;
320 }
321 }
322
323 js_free (cp);
324 break;
325
326 case JS_ARRAY:
327 case JS_OBJECT:
328 case JS_BUILTIN:
329 /* XXX Not implemented yet. */
330 result_return->type = JS_NAN;
331 break;
332
333 case JS_SYMBOL:
334 case JS_FUNC:
335 case JS_IPTR:
336 default:
337 result_return->type = JS_NAN;
338 break;
339 }
340 }
341
342
343 void
344 js_vm_to_object (JSVirtualMachine *vm, const JSNode *n, JSNode *result_return)
345 {
346 switch (n->type)
347 {
348 case JS_BOOLEAN:
349 case JS_INTEGER:
350 case JS_FLOAT:
351 case JS_NAN:
352 case JS_OBJECT:
353 JS_COPY (result_return, n);
354 break;
355
356 case JS_STRING:
357 js_vm_make_string (vm, result_return, (char*)n->u.vstring->data,
358 n->u.vstring->len);
359 break;
360
361 case JS_UNDEFINED:
362 case JS_NULL:
363 default:
364 sprintf (vm->error, "ToObject(): illegal argument");
365 js_vm_error (vm);
366 break;
367 }
368 }
369
370
371 JSInt32
372 js_vm_to_int32 (JSVirtualMachine *vm, JSNode *n)
373 {
374 JSNode intermediate;
375 JSInt32 result;
376
377 js_vm_to_number (vm, n, &intermediate);
378
379 switch (intermediate.type)
380 {
381 case JS_INTEGER:
382 result = (JSInt32) intermediate.u.vinteger;
383 break;
384
385 case JS_FLOAT:
386 if (JS_IS_POSITIVE_INFINITY (&intermediate)
387 || JS_IS_NEGATIVE_INFINITY (&intermediate))
388 result = 0;
389 else
390 result = (JSInt32) intermediate.u.vfloat;
391 break;
392
393 case JS_NAN:
394 default:
395 result = 0;
396 break;
397 }
398
399 return result;
400 }
401
402
403 int
404 js_vm_to_boolean (JSVirtualMachine *vm, JSNode *n)
405 {
406 int result;
407
408 switch (n->type)
409 {
410 case JS_BOOLEAN:
411 result = n->u.vboolean;
412 break;
413
414 case JS_INTEGER:
415 result = n->u.vinteger != 0;
416 break;
417
418 case JS_FLOAT:
419 result = n->u.vfloat != 0;
420 break;
421
422 case JS_STRING:
423 result = n->u.vstring->len > 0;
424 break;
425
426 case JS_OBJECT:
427 result = 1;
428 break;
429
430 case JS_UNDEFINED:
431 case JS_NULL:
432 case JS_NAN:
433 default:
434 result = 0;
435 break;
436 }
437
438 return result;
439 }