1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=99:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla Communicator client code, released
20 * The Initial Developer of the Original Code is
21 * Netscape Communications Corporation.
22 * Portions created by the Initial Developer are Copyright (C) 1998
23 * the Initial Developer. All Rights Reserved.
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 * JS string type implementation.
44 * In order to avoid unnecessary js_LockGCThing/js_UnlockGCThing calls, these
45 * native methods store strings (possibly newborn) converted from their 'this'
46 * parameter and arguments on the stack: 'this' conversions at argv[-1], arg
47 * conversions at their index (argv[0], argv[1]). This is a legitimate method
48 * of rooting things that might lose their newborn root due to subsequent GC
49 * allocations in the same native method.
55 #include "jsutil.h" /* Added by JSIFY */
56 #include "jshash.h" /* Added by JSIFY */
62 #include "jsbuiltins.h"
64 #include "jsversion.h"
76 #define JSSTRDEP_RECURSION_LIMIT 100
79 js_MinimizeDependentStrings(JSString
*str
, int level
, JSString
**basep
)
84 JS_ASSERT(JSSTRING_IS_DEPENDENT(str
));
85 base
= JSSTRDEP_BASE(str
);
86 start
= JSSTRDEP_START(str
);
87 if (JSSTRING_IS_DEPENDENT(base
)) {
88 if (level
< JSSTRDEP_RECURSION_LIMIT
) {
89 start
+= js_MinimizeDependentStrings(base
, level
+ 1, &base
);
92 start
+= JSSTRDEP_START(base
);
93 base
= JSSTRDEP_BASE(base
);
94 } while (JSSTRING_IS_DEPENDENT(base
));
97 JS_ASSERT(JSSTRDEP_IS_PREFIX(str
));
98 JSPREFIX_SET_BASE(str
, base
);
99 } else if (start
<= JSSTRDEP_START_MASK
) {
100 length
= JSSTRDEP_LENGTH(str
);
101 JSSTRDEP_INIT(str
, base
, start
, length
);
109 js_GetDependentStringChars(JSString
*str
)
114 start
= js_MinimizeDependentStrings(str
, 0, &base
);
115 JS_ASSERT(start
< JSFLATSTR_LENGTH(base
));
116 return JSFLATSTR_CHARS(base
) + start
;
120 js_GetStringChars(JSContext
*cx
, JSString
*str
)
122 if (!js_MakeStringImmutable(cx
, str
))
124 return JSFLATSTR_CHARS(str
);
127 JSString
* JS_FASTCALL
128 js_ConcatStrings(JSContext
*cx
, JSString
*left
, JSString
*right
)
130 size_t rn
, ln
, lrdist
, n
;
132 JSString
*ldep
; /* non-null if left should become dependent */
135 JSSTRING_CHARS_AND_LENGTH(right
, rs
, rn
);
139 JSSTRING_CHARS_AND_LENGTH(left
, ls
, ln
);
143 if (!JSSTRING_IS_MUTABLE(left
)) {
144 /* We must copy if left does not own a buffer to realloc. */
145 s
= (jschar
*) JS_malloc(cx
, (ln
+ rn
+ 1) * sizeof(jschar
));
148 js_strncpy(s
, ls
, ln
);
151 /* We can realloc left's space and make it depend on our result. */
152 JS_ASSERT(JSSTRING_IS_FLAT(left
));
153 s
= (jschar
*) JS_realloc(cx
, ls
, (ln
+ rn
+ 1) * sizeof(jschar
));
157 /* Take care: right could depend on left! */
158 lrdist
= (size_t)(rs
- ls
);
161 left
->u
.chars
= ls
= s
;
165 js_strncpy(s
+ ln
, rs
, rn
);
168 str
= js_NewString(cx
, s
, n
);
170 /* Out of memory: clean up any space we (re-)allocated. */
174 s
= (jschar
*) JS_realloc(cx
, ls
, (ln
+ 1) * sizeof(jschar
));
179 JSFLATSTR_SET_MUTABLE(str
);
181 /* Morph left into a dependent prefix if we realloc'd its buffer. */
183 JSPREFIX_INIT(ldep
, str
, ln
);
186 JSRuntime
*rt
= cx
->runtime
;
187 JS_RUNTIME_METER(rt
, liveDependentStrings
);
188 JS_RUNTIME_METER(rt
, totalDependentStrings
);
189 JS_LOCK_RUNTIME_VOID(rt
,
190 (rt
->strdepLengthSum
+= (double)ln
,
191 rt
->strdepLengthSquaredSum
+= (double)ln
* (double)ln
));
201 js_UndependString(JSContext
*cx
, JSString
*str
)
206 if (JSSTRING_IS_DEPENDENT(str
)) {
207 n
= JSSTRDEP_LENGTH(str
);
208 size
= (n
+ 1) * sizeof(jschar
);
209 s
= (jschar
*) JS_malloc(cx
, size
);
213 js_strncpy(s
, JSSTRDEP_CHARS(str
), n
);
215 JSFLATSTR_INIT(str
, s
, n
);
219 JSRuntime
*rt
= cx
->runtime
;
220 JS_RUNTIME_UNMETER(rt
, liveDependentStrings
);
221 JS_RUNTIME_UNMETER(rt
, totalDependentStrings
);
222 JS_LOCK_RUNTIME_VOID(rt
,
223 (rt
->strdepLengthSum
-= (double)n
,
224 rt
->strdepLengthSquaredSum
-= (double)n
* (double)n
));
229 return JSFLATSTR_CHARS(str
);
233 js_MakeStringImmutable(JSContext
*cx
, JSString
*str
)
235 if (JSSTRING_IS_DEPENDENT(str
) && !js_UndependString(cx
, str
)) {
236 JS_RUNTIME_METER(cx
->runtime
, badUndependStrings
);
239 JSFLATSTR_CLEAR_MUTABLE(str
);
244 ArgToRootedString(JSContext
*cx
, uintN argc
, jsval
*vp
, uintN arg
)
250 return ATOM_TO_STRING(cx
->runtime
->atomState
.typeAtoms
[JSTYPE_VOID
]);
253 if (JSVAL_IS_OBJECT(*vp
)) {
254 obj
= JSVAL_TO_OBJECT(*vp
);
256 return ATOM_TO_STRING(cx
->runtime
->atomState
.nullAtom
);
257 if (!OBJ_DEFAULT_VALUE(cx
, obj
, JSTYPE_STRING
, vp
))
260 if (JSVAL_IS_STRING(*vp
))
261 return JSVAL_TO_STRING(*vp
);
262 if (JSVAL_IS_INT(*vp
)) {
263 str
= js_NumberToString(cx
, JSVAL_TO_INT(*vp
));
264 } else if (JSVAL_IS_DOUBLE(*vp
)) {
265 str
= js_NumberToString(cx
, *JSVAL_TO_DOUBLE(*vp
));
266 } else if (JSVAL_IS_BOOLEAN(*vp
)) {
267 return ATOM_TO_STRING(cx
->runtime
->atomState
.booleanAtoms
[
268 JSVAL_TO_BOOLEAN(*vp
)? 1 : 0]);
270 JS_ASSERT(JSVAL_IS_VOID(*vp
));
271 return ATOM_TO_STRING(cx
->runtime
->atomState
.typeAtoms
[JSTYPE_VOID
]);
274 *vp
= STRING_TO_JSVAL(str
);
279 * Forward declarations for URI encode/decode and helper routines
282 str_decodeURI(JSContext
*cx
, uintN argc
, jsval
*vp
);
285 str_decodeURI_Component(JSContext
*cx
, uintN argc
, jsval
*vp
);
288 str_encodeURI(JSContext
*cx
, uintN argc
, jsval
*vp
);
291 str_encodeURI_Component(JSContext
*cx
, uintN argc
, jsval
*vp
);
294 Utf8ToOneUcs4Char(const uint8
*utf8Buffer
, int utf8Length
);
297 * Contributions from the String class to the set of methods defined for the
298 * global object. escape and unescape used to be defined in the Mocha library,
299 * but as ECMA decided to spec them, they've been moved to the core engine
300 * and made ECMA-compliant. (Incomplete escapes are interpreted as literal
301 * characters by unescape.)
305 * Stuff to emulate the old libmocha escape, which took a second argument
306 * giving the type of escape to perform. Retained for compatibility, and
307 * copied here to avoid reliance on net.h, mkparse.c/NET_EscapeBytes.
310 #define URL_XALPHAS ((uint8) 1)
311 #define URL_XPALPHAS ((uint8) 2)
312 #define URL_PATH ((uint8) 4)
314 static const uint8 urlCharType
[256] =
315 /* Bit 0 xalpha -- the alphas
316 * Bit 1 xpalpha -- as xalpha but
317 * converts spaces to plus and plus to %20
318 * Bit 2 ... path -- as xalphas but doesn't escape '/'
320 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
321 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x */
322 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1x */
323 0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4, /* 2x !"#$%&'()*+,-./ */
324 7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
325 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 4x @ABCDEFGHIJKLMNO */
326 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7, /* 5X PQRSTUVWXYZ[\]^_ */
327 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 6x `abcdefghijklmno */
328 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0, /* 7X pqrstuvwxyz{\}~ DEL */
331 /* This matches the ECMA escape set when mask is 7 (default.) */
333 #define IS_OK(C, mask) (urlCharType[((uint8) (C))] & (mask))
335 /* See ECMA-262 Edition 3 B.2.1 */
337 js_str_escape(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
340 size_t i
, ni
, length
, newlength
;
346 const char digits
[] = {'0', '1', '2', '3', '4', '5', '6', '7',
347 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
349 mask
= URL_XALPHAS
| URL_XPALPHAS
| URL_PATH
;
351 d
= js_ValueToNumber(cx
, &argv
[1]);
352 if (JSVAL_IS_NULL(argv
[1]))
354 if (!JSDOUBLE_IS_FINITE(d
) ||
355 (mask
= (jsint
)d
) != d
||
356 mask
& ~(URL_XALPHAS
| URL_XPALPHAS
| URL_PATH
))
359 JS_snprintf(numBuf
, sizeof numBuf
, "%lx", (unsigned long) mask
);
360 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
361 JSMSG_BAD_STRING_MASK
, numBuf
);
366 str
= ArgToRootedString(cx
, argc
, argv
- 2, 0);
370 JSSTRING_CHARS_AND_LENGTH(str
, chars
, length
);
373 /* Take a first pass and see how big the result string will need to be. */
374 for (i
= 0; i
< length
; i
++) {
375 if ((ch
= chars
[i
]) < 128 && IS_OK(ch
, mask
))
378 if (mask
== URL_XPALPHAS
&& ch
== ' ')
379 continue; /* The character will be encoded as '+' */
380 newlength
+= 2; /* The character will be encoded as %XX */
382 newlength
+= 5; /* The character will be encoded as %uXXXX */
386 * This overflow test works because newlength is incremented by at
387 * most 5 on each iteration.
389 if (newlength
< length
) {
390 js_ReportAllocationOverflow(cx
);
395 if (newlength
>= ~(size_t)0 / sizeof(jschar
)) {
396 js_ReportAllocationOverflow(cx
);
400 newchars
= (jschar
*) JS_malloc(cx
, (newlength
+ 1) * sizeof(jschar
));
403 for (i
= 0, ni
= 0; i
< length
; i
++) {
404 if ((ch
= chars
[i
]) < 128 && IS_OK(ch
, mask
)) {
406 } else if (ch
< 256) {
407 if (mask
== URL_XPALPHAS
&& ch
== ' ') {
408 newchars
[ni
++] = '+'; /* convert spaces to pluses */
410 newchars
[ni
++] = '%';
411 newchars
[ni
++] = digits
[ch
>> 4];
412 newchars
[ni
++] = digits
[ch
& 0xF];
415 newchars
[ni
++] = '%';
416 newchars
[ni
++] = 'u';
417 newchars
[ni
++] = digits
[ch
>> 12];
418 newchars
[ni
++] = digits
[(ch
& 0xF00) >> 8];
419 newchars
[ni
++] = digits
[(ch
& 0xF0) >> 4];
420 newchars
[ni
++] = digits
[ch
& 0xF];
423 JS_ASSERT(ni
== newlength
);
424 newchars
[newlength
] = 0;
426 str
= js_NewString(cx
, newchars
, newlength
);
428 JS_free(cx
, newchars
);
431 *rval
= STRING_TO_JSVAL(str
);
437 str_escape(JSContext
*cx
, uintN argc
, jsval
*vp
)
441 obj
= JS_THIS_OBJECT(cx
, vp
);
442 return obj
&& js_str_escape(cx
, obj
, argc
, vp
+ 2, vp
);
445 /* See ECMA-262 Edition 3 B.2.2 */
447 str_unescape(JSContext
*cx
, uintN argc
, jsval
*vp
)
450 size_t i
, ni
, length
;
455 str
= ArgToRootedString(cx
, argc
, vp
, 0);
459 JSSTRING_CHARS_AND_LENGTH(str
, chars
, length
);
461 /* Don't bother allocating less space for the new string. */
462 newchars
= (jschar
*) JS_malloc(cx
, (length
+ 1) * sizeof(jschar
));
469 if (i
+ 1 < length
&&
470 JS7_ISHEX(chars
[i
]) && JS7_ISHEX(chars
[i
+ 1]))
472 ch
= JS7_UNHEX(chars
[i
]) * 16 + JS7_UNHEX(chars
[i
+ 1]);
474 } else if (i
+ 4 < length
&& chars
[i
] == 'u' &&
475 JS7_ISHEX(chars
[i
+ 1]) && JS7_ISHEX(chars
[i
+ 2]) &&
476 JS7_ISHEX(chars
[i
+ 3]) && JS7_ISHEX(chars
[i
+ 4]))
478 ch
= (((((JS7_UNHEX(chars
[i
+ 1]) << 4)
479 + JS7_UNHEX(chars
[i
+ 2])) << 4)
480 + JS7_UNHEX(chars
[i
+ 3])) << 4)
481 + JS7_UNHEX(chars
[i
+ 4]);
489 str
= js_NewString(cx
, newchars
, ni
);
491 JS_free(cx
, newchars
);
494 *vp
= STRING_TO_JSVAL(str
);
500 str_uneval(JSContext
*cx
, uintN argc
, jsval
*vp
)
504 str
= js_ValueToSource(cx
, argc
!= 0 ? vp
[2] : JSVAL_VOID
);
507 *vp
= STRING_TO_JSVAL(str
);
512 const char js_escape_str
[] = "escape";
513 const char js_unescape_str
[] = "unescape";
515 const char js_uneval_str
[] = "uneval";
517 const char js_decodeURI_str
[] = "decodeURI";
518 const char js_encodeURI_str
[] = "encodeURI";
519 const char js_decodeURIComponent_str
[] = "decodeURIComponent";
520 const char js_encodeURIComponent_str
[] = "encodeURIComponent";
522 static JSFunctionSpec string_functions
[] = {
523 JS_FN(js_escape_str
, str_escape
, 1,0),
524 JS_FN(js_unescape_str
, str_unescape
, 1,0),
526 JS_FN(js_uneval_str
, str_uneval
, 1,0),
528 JS_FN(js_decodeURI_str
, str_decodeURI
, 1,0),
529 JS_FN(js_encodeURI_str
, str_encodeURI
, 1,0),
530 JS_FN(js_decodeURIComponent_str
, str_decodeURI_Component
, 1,0),
531 JS_FN(js_encodeURIComponent_str
, str_encodeURI_Component
, 1,0),
536 jschar js_empty_ucstr
[] = {0};
537 JSSubString js_EmptySubString
= {0, js_empty_ucstr
};
543 static JSPropertySpec string_props
[] = {
544 {js_length_str
, STRING_LENGTH
,
545 JSPROP_READONLY
|JSPROP_PERMANENT
|JSPROP_SHARED
, 0,0},
550 str_getProperty(JSContext
*cx
, JSObject
*obj
, jsval id
, jsval
*vp
)
556 if (!JSVAL_IS_INT(id
))
559 slot
= JSVAL_TO_INT(id
);
560 if (slot
== STRING_LENGTH
) {
561 if (OBJ_GET_CLASS(cx
, obj
) == &js_StringClass
) {
562 /* Follow ECMA-262 by fetching intrinsic length of our string. */
563 v
= OBJ_GET_SLOT(cx
, obj
, JSSLOT_PRIVATE
);
564 JS_ASSERT(JSVAL_IS_STRING(v
));
565 str
= JSVAL_TO_STRING(v
);
567 /* Preserve compatibility: convert obj to a string primitive. */
568 str
= js_ValueToString(cx
, OBJECT_TO_JSVAL(obj
));
573 *vp
= INT_TO_JSVAL((jsint
) JSSTRING_LENGTH(str
));
578 #define STRING_ELEMENT_ATTRS (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
581 str_enumerate(JSContext
*cx
, JSObject
*obj
)
584 JSString
*str
, *str1
;
587 v
= OBJ_GET_SLOT(cx
, obj
, JSSLOT_PRIVATE
);
588 JS_ASSERT(JSVAL_IS_STRING(v
));
589 str
= JSVAL_TO_STRING(v
);
591 length
= JSSTRING_LENGTH(str
);
592 for (i
= 0; i
< length
; i
++) {
593 str1
= js_NewDependentString(cx
, str
, i
, 1);
596 if (!OBJ_DEFINE_PROPERTY(cx
, obj
, INT_TO_JSID(i
),
597 STRING_TO_JSVAL(str1
), NULL
, NULL
,
598 STRING_ELEMENT_ATTRS
, NULL
)) {
606 str_resolve(JSContext
*cx
, JSObject
*obj
, jsval id
, uintN flags
,
610 JSString
*str
, *str1
;
613 if (!JSVAL_IS_INT(id
) || (flags
& JSRESOLVE_ASSIGNING
))
616 v
= OBJ_GET_SLOT(cx
, obj
, JSSLOT_PRIVATE
);
617 JS_ASSERT(JSVAL_IS_STRING(v
));
618 str
= JSVAL_TO_STRING(v
);
620 slot
= JSVAL_TO_INT(id
);
621 if ((size_t)slot
< JSSTRING_LENGTH(str
)) {
622 str1
= js_GetUnitString(cx
, str
, (size_t)slot
);
625 if (!OBJ_DEFINE_PROPERTY(cx
, obj
, INT_TO_JSID(slot
),
626 STRING_TO_JSVAL(str1
), NULL
, NULL
,
627 STRING_ELEMENT_ATTRS
, NULL
)) {
635 JSClass js_StringClass
= {
637 JSCLASS_HAS_PRIVATE
| JSCLASS_NEW_RESOLVE
|
638 JSCLASS_HAS_CACHED_PROTO(JSProto_String
),
639 JS_PropertyStub
, JS_PropertyStub
, str_getProperty
, JS_PropertyStub
,
640 str_enumerate
, (JSResolveOp
)str_resolve
, JS_ConvertStub
, JS_FinalizeStub
,
641 JSCLASS_NO_OPTIONAL_MEMBERS
644 #define NORMALIZE_THIS(cx,vp,str) \
646 if (JSVAL_IS_STRING(vp[1])) { \
647 str = JSVAL_TO_STRING(vp[1]); \
649 str = NormalizeThis(cx, vp); \
656 NormalizeThis(JSContext
*cx
, jsval
*vp
)
660 if (JSVAL_IS_NULL(vp
[1]) && JSVAL_IS_NULL(JS_THIS(cx
, vp
)))
662 str
= js_ValueToString(cx
, vp
[1]);
665 vp
[1] = STRING_TO_JSVAL(str
);
672 * String.prototype.quote is generic (as are most string methods), unlike
673 * toSource, toString, and valueOf.
676 str_quote(JSContext
*cx
, uintN argc
, jsval
*vp
)
680 NORMALIZE_THIS(cx
, vp
, str
);
681 str
= js_QuoteString(cx
, str
, '"');
684 *vp
= STRING_TO_JSVAL(str
);
689 str_toSource(JSContext
*cx
, uintN argc
, jsval
*vp
)
697 if (!js_GetPrimitiveThis(cx
, vp
, &js_StringClass
, &v
))
699 JS_ASSERT(JSVAL_IS_STRING(v
));
700 str
= js_QuoteString(cx
, JSVAL_TO_STRING(v
), '"');
703 j
= JS_snprintf(buf
, sizeof buf
, "(new %s(", js_StringClass
.name
);
704 JSSTRING_CHARS_AND_LENGTH(str
, s
, k
);
706 t
= (jschar
*) JS_malloc(cx
, (n
+ 1) * sizeof(jschar
));
709 for (i
= 0; i
< j
; i
++)
711 for (j
= 0; j
< k
; i
++, j
++)
716 str
= js_NewString(cx
, t
, n
);
721 *vp
= STRING_TO_JSVAL(str
);
725 #endif /* JS_HAS_TOSOURCE */
728 str_toString(JSContext
*cx
, uintN argc
, jsval
*vp
)
730 return js_GetPrimitiveThis(cx
, vp
, &js_StringClass
, vp
);
734 * Java-like string native methods.
738 SubstringTail(JSContext
*cx
, JSString
*str
, jsdouble length
, jsdouble begin
, jsdouble end
)
742 else if (begin
> length
)
747 else if (end
> length
)
750 /* ECMA emulates old JDK1.0 java.lang.String.substring. */
751 jsdouble tmp
= begin
;
756 return js_NewDependentString(cx
, str
, (size_t)begin
, (size_t)(end
- begin
));
760 str_substring(JSContext
*cx
, uintN argc
, jsval
*vp
)
764 jsdouble length
, begin
, end
;
766 NORMALIZE_THIS(cx
, vp
, str
);
768 d
= js_ValueToNumber(cx
, &vp
[2]);
769 if (JSVAL_IS_NULL(vp
[2]))
771 length
= JSSTRING_LENGTH(str
);
772 begin
= js_DoubleToInteger(d
);
776 d
= js_ValueToNumber(cx
, &vp
[3]);
777 if (JSVAL_IS_NULL(vp
[3]))
779 end
= js_DoubleToInteger(d
);
782 str
= SubstringTail(cx
, str
, length
, begin
, end
);
786 *vp
= STRING_TO_JSVAL(str
);
791 static JSString
* FASTCALL
792 String_p_toString(JSContext
* cx
, JSObject
* obj
)
794 if (!JS_InstanceOf(cx
, obj
, &js_StringClass
, NULL
))
796 jsval v
= OBJ_GET_SLOT(cx
, obj
, JSSLOT_PRIVATE
);
797 JS_ASSERT(JSVAL_IS_STRING(v
));
798 return JSVAL_TO_STRING(v
);
801 static JSString
* FASTCALL
802 String_p_substring(JSContext
* cx
, JSString
* str
, int32 begin
, int32 end
)
804 JS_ASSERT(JS_ON_TRACE(cx
));
806 size_t length
= JSSTRING_LENGTH(str
);
807 return SubstringTail(cx
, str
, length
, begin
, end
);
810 static JSString
* FASTCALL
811 String_p_substring_1(JSContext
* cx
, JSString
* str
, int32 begin
)
813 JS_ASSERT(JS_ON_TRACE(cx
));
815 size_t length
= JSSTRING_LENGTH(str
);
816 return SubstringTail(cx
, str
, length
, begin
, length
);
820 JSString
* JS_FASTCALL
821 js_toLowerCase(JSContext
*cx
, JSString
*str
)
826 JSSTRING_CHARS_AND_LENGTH(str
, s
, n
);
827 news
= (jschar
*) JS_malloc(cx
, (n
+ 1) * sizeof(jschar
));
830 for (i
= 0; i
< n
; i
++)
831 news
[i
] = JS_TOLOWER(s
[i
]);
833 str
= js_NewString(cx
, news
, n
);
842 str_toLowerCase(JSContext
*cx
, uintN argc
, jsval
*vp
)
846 NORMALIZE_THIS(cx
, vp
, str
);
847 str
= js_toLowerCase(cx
, str
);
850 *vp
= STRING_TO_JSVAL(str
);
855 str_toLocaleLowerCase(JSContext
*cx
, uintN argc
, jsval
*vp
)
860 * Forcefully ignore the first (or any) argument and return toLowerCase(),
861 * ECMA has reserved that argument, presumably for defining the locale.
863 if (cx
->localeCallbacks
&& cx
->localeCallbacks
->localeToLowerCase
) {
864 NORMALIZE_THIS(cx
, vp
, str
);
865 return cx
->localeCallbacks
->localeToLowerCase(cx
, str
, vp
);
867 return str_toLowerCase(cx
, 0, vp
);
870 JSString
* JS_FASTCALL
871 js_toUpperCase(JSContext
*cx
, JSString
*str
)
876 JSSTRING_CHARS_AND_LENGTH(str
, s
, n
);
877 news
= (jschar
*) JS_malloc(cx
, (n
+ 1) * sizeof(jschar
));
880 for (i
= 0; i
< n
; i
++)
881 news
[i
] = JS_TOUPPER(s
[i
]);
883 str
= js_NewString(cx
, news
, n
);
892 str_toUpperCase(JSContext
*cx
, uintN argc
, jsval
*vp
)
896 NORMALIZE_THIS(cx
, vp
, str
);
897 str
= js_toUpperCase(cx
, str
);
900 *vp
= STRING_TO_JSVAL(str
);
905 str_toLocaleUpperCase(JSContext
*cx
, uintN argc
, jsval
*vp
)
910 * Forcefully ignore the first (or any) argument and return toUpperCase(),
911 * ECMA has reserved that argument, presumably for defining the locale.
913 if (cx
->localeCallbacks
&& cx
->localeCallbacks
->localeToUpperCase
) {
914 NORMALIZE_THIS(cx
, vp
, str
);
915 return cx
->localeCallbacks
->localeToUpperCase(cx
, str
, vp
);
917 return str_toUpperCase(cx
, 0, vp
);
921 str_localeCompare(JSContext
*cx
, uintN argc
, jsval
*vp
)
923 JSString
*str
, *thatStr
;
925 NORMALIZE_THIS(cx
, vp
, str
);
929 thatStr
= js_ValueToString(cx
, vp
[2]);
932 if (cx
->localeCallbacks
&& cx
->localeCallbacks
->localeCompare
) {
933 vp
[2] = STRING_TO_JSVAL(thatStr
);
934 return cx
->localeCallbacks
->localeCompare(cx
, str
, thatStr
, vp
);
936 *vp
= INT_TO_JSVAL(js_CompareStrings(str
, thatStr
));
942 str_charAt(JSContext
*cx
, uintN argc
, jsval
*vp
)
950 if (JSVAL_IS_STRING(t
) && argc
!= 0 && JSVAL_IS_INT(vp
[2])) {
951 str
= JSVAL_TO_STRING(t
);
952 i
= JSVAL_TO_INT(vp
[2]);
953 if ((size_t)i
>= JSSTRING_LENGTH(str
))
956 str
= NormalizeThis(cx
, vp
);
963 d
= js_ValueToNumber(cx
, &vp
[2]);
964 if (JSVAL_IS_NULL(vp
[2]))
966 d
= js_DoubleToInteger(d
);
969 if (d
< 0 || JSSTRING_LENGTH(str
) <= d
)
974 str
= js_GetUnitString(cx
, str
, (size_t)i
);
977 *vp
= STRING_TO_JSVAL(str
);
981 *vp
= JS_GetEmptyStringValue(cx
);
986 str_charCodeAt(JSContext
*cx
, uintN argc
, jsval
*vp
)
994 if (JSVAL_IS_STRING(t
) && argc
!= 0 && JSVAL_IS_INT(vp
[2])) {
995 str
= JSVAL_TO_STRING(t
);
996 i
= JSVAL_TO_INT(vp
[2]);
997 if ((size_t)i
>= JSSTRING_LENGTH(str
))
1000 str
= NormalizeThis(cx
, vp
);
1007 d
= js_ValueToNumber(cx
, &vp
[2]);
1008 if (JSVAL_IS_NULL(vp
[2]))
1010 d
= js_DoubleToInteger(d
);
1013 if (d
< 0 || JSSTRING_LENGTH(str
) <= d
)
1018 *vp
= INT_TO_JSVAL(JSSTRING_CHARS(str
)[i
]);
1022 *vp
= JS_GetNaNValue(cx
);
1028 js_String_p_charCodeAt(JSString
* str
, int32 i
)
1030 if (i
< 0 || (int32
)JSSTRING_LENGTH(str
) <= i
)
1032 return JSSTRING_CHARS(str
)[i
];
1037 js_BoyerMooreHorspool(const jschar
*text
, jsint textlen
,
1038 const jschar
*pat
, jsint patlen
,
1042 uint8 skip
[BMH_CHARSET_SIZE
];
1045 JS_ASSERT(0 < patlen
&& patlen
<= BMH_PATLEN_MAX
);
1046 for (i
= 0; i
< BMH_CHARSET_SIZE
; i
++)
1047 skip
[i
] = (uint8
)patlen
;
1049 for (i
= 0; i
< m
; i
++) {
1051 if (c
>= BMH_CHARSET_SIZE
)
1052 return BMH_BAD_PATTERN
;
1053 skip
[c
] = (uint8
)(m
- i
);
1057 k
+= ((c
= text
[k
]) >= BMH_CHARSET_SIZE
) ? patlen
: skip
[c
]) {
1058 for (i
= k
, j
= m
; ; i
--, j
--) {
1061 if (text
[i
] != pat
[j
])
1069 str_indexOf(JSContext
*cx
, uintN argc
, jsval
*vp
)
1072 JSString
*str
, *str2
;
1073 const jschar
*text
, *pat
;
1074 jsint i
, j
, index
, textlen
, patlen
;
1078 if (JSVAL_IS_STRING(t
) && argc
!= 0 && JSVAL_IS_STRING(vp
[2])) {
1079 str
= JSVAL_TO_STRING(t
);
1080 str2
= JSVAL_TO_STRING(vp
[2]);
1082 str
= NormalizeThis(cx
, vp
);
1086 str2
= ArgToRootedString(cx
, argc
, vp
, 0);
1091 text
= JSSTRING_CHARS(str
);
1092 textlen
= (jsint
) JSSTRING_LENGTH(str
);
1093 pat
= JSSTRING_CHARS(str2
);
1094 patlen
= (jsint
) JSSTRING_LENGTH(str2
);
1097 d
= js_ValueToNumber(cx
, &vp
[3]);
1098 if (JSVAL_IS_NULL(vp
[3]))
1100 d
= js_DoubleToInteger(d
);
1103 else if (d
> textlen
)
1111 *vp
= INT_TO_JSVAL(i
);
1115 /* XXX tune the BMH threshold (512) */
1116 if (textlen
- i
>= 512 && (jsuint
)(patlen
- 2) <= BMH_PATLEN_MAX
- 2) {
1117 index
= js_BoyerMooreHorspool(text
, textlen
, pat
, patlen
, i
);
1118 if (index
!= BMH_BAD_PATTERN
)
1124 while (i
+ j
< textlen
) {
1125 if (text
[i
+ j
] == pat
[j
]) {
1126 if (++j
== patlen
) {
1137 *vp
= INT_TO_JSVAL(index
);
1142 str_lastIndexOf(JSContext
*cx
, uintN argc
, jsval
*vp
)
1144 JSString
*str
, *str2
;
1145 const jschar
*text
, *pat
;
1146 jsint i
, j
, textlen
, patlen
;
1149 NORMALIZE_THIS(cx
, vp
, str
);
1150 text
= JSSTRING_CHARS(str
);
1151 textlen
= (jsint
) JSSTRING_LENGTH(str
);
1153 str2
= ArgToRootedString(cx
, argc
, vp
, 0);
1156 pat
= JSSTRING_CHARS(str2
);
1157 patlen
= (jsint
) JSSTRING_LENGTH(str2
);
1160 d
= js_ValueToNumber(cx
, &vp
[3]);
1161 if (JSVAL_IS_NULL(vp
[3]))
1163 if (JSDOUBLE_IS_NaN(d
)) {
1166 d
= js_DoubleToInteger(d
);
1169 else if (d
> textlen
)
1179 *vp
= INT_TO_JSVAL(i
);
1185 /* Don't assume that text is NUL-terminated: it could be dependent. */
1186 if (i
+ j
< textlen
&& text
[i
+ j
] == pat
[j
]) {
1194 *vp
= INT_TO_JSVAL(i
);
1199 js_TrimString(JSContext
*cx
, jsval
*vp
, JSBool trimLeft
, JSBool trimRight
)
1202 const jschar
*chars
;
1203 size_t length
, begin
, end
;
1205 NORMALIZE_THIS(cx
, vp
, str
);
1206 JSSTRING_CHARS_AND_LENGTH(str
, chars
, length
);
1211 while (begin
< length
&& JS_ISSPACE(chars
[begin
]))
1216 while (end
> begin
&& JS_ISSPACE(chars
[end
-1]))
1220 str
= js_NewDependentString(cx
, str
, begin
, end
- begin
);
1224 *vp
= STRING_TO_JSVAL(str
);
1229 str_trim(JSContext
*cx
, uintN argc
, jsval
*vp
)
1231 return js_TrimString(cx
, vp
, JS_TRUE
, JS_TRUE
);
1235 str_trimLeft(JSContext
*cx
, uintN argc
, jsval
*vp
)
1237 return js_TrimString(cx
, vp
, JS_TRUE
, JS_FALSE
);
1241 str_trimRight(JSContext
*cx
, uintN argc
, jsval
*vp
)
1243 return js_TrimString(cx
, vp
, JS_FALSE
, JS_TRUE
);
1247 * Perl-inspired string functions.
1249 typedef struct GlobData
{
1250 jsbytecode
*pc
; /* in: program counter resulting in us matching */
1251 uintN flags
; /* inout: mode and flag bits, see below */
1252 uintN optarg
; /* in: index of optional flags argument */
1253 JSString
*str
; /* out: 'this' parameter object as string */
1254 JSRegExp
*regexp
; /* out: regexp parameter object private data */
1258 * Mode and flag bit definitions for match_or_replace's GlobData.flags field.
1260 #define MODE_MATCH 0x00 /* in: return match array on success */
1261 #define MODE_REPLACE 0x01 /* in: match and replace */
1262 #define MODE_SEARCH 0x02 /* in: search only, return match index or -1 */
1263 #define GET_MODE(f) ((f) & 0x03)
1264 #define FORCE_FLAT 0x04 /* in: force flat (non-regexp) string match */
1265 #define KEEP_REGEXP 0x08 /* inout: keep GlobData.regexp alive for caller
1266 of match_or_replace; if set on input
1267 but clear on output, regexp ownership
1268 does not pass to caller */
1269 #define GLOBAL_REGEXP 0x10 /* out: regexp had the 'g' flag */
1272 match_or_replace(JSContext
*cx
,
1273 JSBool (*glob
)(JSContext
*cx
, jsint count
, GlobData
*data
),
1274 void (*destroy
)(JSContext
*cx
, GlobData
*data
),
1275 GlobData
*data
, uintN argc
, jsval
*vp
)
1277 JSString
*str
, *src
, *opt
;
1280 size_t index
, length
;
1284 NORMALIZE_THIS(cx
, vp
, str
);
1287 if (argc
!= 0 && VALUE_IS_REGEXP(cx
, vp
[2])) {
1288 reobj
= JSVAL_TO_OBJECT(vp
[2]);
1289 re
= (JSRegExp
*) JS_GetPrivate(cx
, reobj
);
1291 src
= ArgToRootedString(cx
, argc
, vp
, 0);
1294 if (data
->optarg
< argc
) {
1295 opt
= js_ValueToString(cx
, vp
[2 + data
->optarg
]);
1301 re
= js_NewRegExpOpt(cx
, src
, opt
, (data
->flags
& FORCE_FLAT
) != 0);
1306 /* From here on, all control flow must reach the matching DROP. */
1308 HOLD_REGEXP(cx
, re
);
1310 if (re
->flags
& JSREG_GLOB
)
1311 data
->flags
|= GLOBAL_REGEXP
;
1313 if (GET_MODE(data
->flags
) == MODE_SEARCH
) {
1314 ok
= js_ExecuteRegExp(cx
, re
, str
, &index
, JS_TRUE
, vp
);
1316 *vp
= (*vp
== JSVAL_TRUE
)
1317 ? INT_TO_JSVAL(cx
->regExpStatics
.leftContext
.length
)
1320 } else if (data
->flags
& GLOBAL_REGEXP
) {
1322 /* Set the lastIndex property's reserved slot to 0. */
1323 ok
= js_SetLastIndex(cx
, reobj
, 0);
1328 length
= JSSTRING_LENGTH(str
);
1329 for (count
= 0; index
<= length
; count
++) {
1330 ok
= js_ExecuteRegExp(cx
, re
, str
, &index
, JS_TRUE
, vp
);
1331 if (!ok
|| *vp
!= JSVAL_TRUE
)
1333 ok
= glob(cx
, count
, data
);
1336 if (cx
->regExpStatics
.lastMatch
.length
== 0) {
1337 if (index
== length
)
1346 jsval savedObject
= JSVAL_NULL
;
1348 if (GET_MODE(data
->flags
) == MODE_REPLACE
) {
1352 * MODE_MATCH implies str_match is being called from a script or a
1353 * scripted function. If the caller cares only about testing null
1354 * vs. non-null return value, optimize away the array object that
1355 * would normally be returned in *vp. Instead return an arbitrary
1356 * object (not JSVAL_TRUE, for type map integrity; see bug 453564).
1357 * The caller provides the object in *vp and is responsible for
1358 * rooting it elsewhere.
1360 * Assume a full array result is required, then prove otherwise.
1363 if (data
->pc
&& (*data
->pc
== JSOP_CALL
|| *data
->pc
== JSOP_NEW
)) {
1364 JS_ASSERT(js_CodeSpec
[*data
->pc
].length
== 3);
1365 switch (data
->pc
[3]) {
1373 JS_ASSERT(!JSVAL_IS_PRIMITIVE(savedObject
));
1379 ok
= js_ExecuteRegExp(cx
, re
, str
, &index
, test
, vp
);
1380 if (ok
&& !JSVAL_IS_NULL(savedObject
) && *vp
== JSVAL_TRUE
)
1384 DROP_REGEXP(cx
, re
);
1386 /* Tell our caller that it doesn't need to destroy data->regexp. */
1387 data
->flags
&= ~KEEP_REGEXP
;
1388 } else if (!ok
|| !(data
->flags
& KEEP_REGEXP
)) {
1389 /* Caller didn't want to keep data->regexp, so null and destroy it. */
1390 data
->regexp
= NULL
;
1391 js_DestroyRegExp(cx
, re
);
1397 typedef struct MatchData
{
1399 jsval
*arrayval
; /* NB: local root pointer */
1403 match_glob(JSContext
*cx
, jsint count
, GlobData
*data
)
1407 JSSubString
*matchsub
;
1411 mdata
= (MatchData
*)data
;
1412 arrayobj
= JSVAL_TO_OBJECT(*mdata
->arrayval
);
1414 arrayobj
= js_NewArrayObject(cx
, 0, NULL
);
1417 *mdata
->arrayval
= OBJECT_TO_JSVAL(arrayobj
);
1419 matchsub
= &cx
->regExpStatics
.lastMatch
;
1420 matchstr
= js_NewStringCopyN(cx
, matchsub
->chars
, matchsub
->length
);
1423 v
= STRING_TO_JSVAL(matchstr
);
1424 JS_ASSERT(count
<= JSVAL_INT_MAX
);
1426 JSAutoResolveFlags
rf(cx
, JSRESOLVE_QUALIFIED
| JSRESOLVE_ASSIGNING
);
1427 return OBJ_SET_PROPERTY(cx
, arrayobj
, INT_TO_JSID(count
), &v
);
1431 StringMatchHelper(JSContext
*cx
, uintN argc
, jsval
*vp
, jsbytecode
*pc
)
1433 JSTempValueRooter tvr
;
1437 JS_PUSH_SINGLE_TEMP_ROOT(cx
, JSVAL_NULL
, &tvr
);
1439 mdata
.base
.flags
= MODE_MATCH
;
1440 mdata
.base
.optarg
= 1;
1441 mdata
.arrayval
= &tvr
.u
.value
;
1442 ok
= match_or_replace(cx
, match_glob
, NULL
, &mdata
.base
, argc
, vp
);
1443 if (ok
&& !JSVAL_IS_NULL(*mdata
.arrayval
))
1444 *vp
= *mdata
.arrayval
;
1445 JS_POP_TEMP_ROOT(cx
, &tvr
);
1450 str_match(JSContext
*cx
, uintN argc
, jsval
*vp
)
1454 for (fp
= js_GetTopStackFrame(cx
); fp
&& !fp
->regs
; fp
= fp
->down
)
1455 JS_ASSERT(!fp
->script
);
1457 /* Root the object in vp[0]. See comment in match_or_replace. */
1458 JSAutoTempValueRooter
tvr(cx
, vp
[0]);
1459 return StringMatchHelper(cx
, argc
, vp
, fp
? fp
->regs
->pc
: NULL
);
1463 static JSObject
* FASTCALL
1464 String_p_match(JSContext
* cx
, JSString
* str
, jsbytecode
*pc
, JSObject
* regexp
)
1466 /* arbitrary object in vp[0] */
1467 jsval vp
[3] = { OBJECT_TO_JSVAL(regexp
), STRING_TO_JSVAL(str
), OBJECT_TO_JSVAL(regexp
) };
1468 if (!StringMatchHelper(cx
, 1, vp
, pc
))
1469 return (JSObject
*) JSVAL_TO_BOOLEAN(JSVAL_VOID
);
1470 JS_ASSERT(JSVAL_IS_OBJECT(vp
[0]));
1471 return JSVAL_TO_OBJECT(vp
[0]);
1474 static JSObject
* FASTCALL
1475 String_p_match_obj(JSContext
* cx
, JSObject
* str
, jsbytecode
*pc
, JSObject
* regexp
)
1477 /* arbitrary object in vp[0] */
1478 jsval vp
[3] = { OBJECT_TO_JSVAL(regexp
), OBJECT_TO_JSVAL(str
), OBJECT_TO_JSVAL(regexp
) };
1479 if (!StringMatchHelper(cx
, 1, vp
, pc
))
1480 return (JSObject
*) JSVAL_TO_BOOLEAN(JSVAL_VOID
);
1481 JS_ASSERT(JSVAL_IS_OBJECT(vp
[0]));
1482 return JSVAL_TO_OBJECT(vp
[0]);
1487 str_search(JSContext
*cx
, uintN argc
, jsval
*vp
)
1491 data
.flags
= MODE_SEARCH
;
1493 return match_or_replace(cx
, NULL
, NULL
, &data
, argc
, vp
);
1496 typedef struct ReplaceData
{
1497 GlobData base
; /* base struct state */
1498 JSObject
*lambda
; /* replacement function object or null */
1499 JSString
*repstr
; /* replacement string */
1500 jschar
*dollar
; /* null or pointer to first $ in repstr */
1501 jschar
*dollarEnd
; /* limit pointer for js_strchr_limit */
1502 jschar
*chars
; /* result chars, null initially */
1503 size_t length
; /* result length, 0 initially */
1504 jsint index
; /* index in result of next replacement */
1505 jsint leftIndex
; /* left context index in base.str->chars */
1506 JSSubString dollarStr
; /* for "$$" interpret_dollar result */
1509 static JSSubString
*
1510 interpret_dollar(JSContext
*cx
, jschar
*dp
, jschar
*ep
, ReplaceData
*rdata
,
1513 JSRegExpStatics
*res
;
1517 JS_ASSERT(*dp
== '$');
1519 /* If there is only a dollar, bail now */
1523 /* Interpret all Perl match-induced dollar variables. */
1524 res
= &cx
->regExpStatics
;
1526 if (JS7_ISDEC(dc
)) {
1527 /* ECMA-262 Edition 3: 1-9 or 01-99 */
1528 num
= JS7_UNDEC(dc
);
1529 if (num
> res
->parenCount
)
1533 if (cp
< ep
&& (dc
= *cp
, JS7_ISDEC(dc
))) {
1534 tmp
= 10 * num
+ JS7_UNDEC(dc
);
1535 if (tmp
<= res
->parenCount
) {
1543 /* Adjust num from 1 $n-origin to 0 array-index-origin. */
1546 return REGEXP_PAREN_SUBSTRING(res
, num
);
1552 rdata
->dollarStr
.chars
= dp
;
1553 rdata
->dollarStr
.length
= 1;
1554 return &rdata
->dollarStr
;
1556 return &res
->lastMatch
;
1558 return &res
->lastParen
;
1560 return &res
->leftContext
;
1562 return &res
->rightContext
;
1568 find_replen(JSContext
*cx
, ReplaceData
*rdata
, size_t *sizep
)
1571 size_t replen
, skip
;
1576 lambda
= rdata
->lambda
;
1578 uintN argc
, i
, j
, m
, n
, p
;
1579 jsval
*invokevp
, *sp
;
1584 * Save the regExpStatics from the current regexp, since they may be
1585 * clobbered by a RegExp usage in the lambda function. Note that all
1586 * members of JSRegExpStatics are JSSubStrings, so not GC roots, save
1587 * input, which is rooted otherwise via vp[1] in str_replace.
1589 JSRegExpStatics save
= cx
->regExpStatics
;
1590 JSBool freeMoreParens
= JS_FALSE
;
1593 * In the lambda case, not only do we find the replacement string's
1594 * length, we compute repstr and return it via rdata for use within
1595 * do_replace. The lambda is called with arguments ($&, $1, $2, ...,
1596 * index, input), i.e., all the properties of a regexp match array.
1597 * For $&, etc., we must create string jsvals from cx->regExpStatics.
1598 * We grab up stack space to keep the newborn strings GC-rooted.
1600 p
= rdata
->base
.regexp
->parenCount
;
1602 invokevp
= js_AllocStack(cx
, 2 + argc
, &mark
);
1606 /* Push lambda and its 'this' parameter. */
1608 *sp
++ = OBJECT_TO_JSVAL(lambda
);
1609 *sp
++ = OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx
, lambda
));
1611 #define PUSH_REGEXP_STATIC(sub) \
1613 JSString *str = js_NewStringCopyN(cx, \
1614 cx->regExpStatics.sub.chars, \
1615 cx->regExpStatics.sub.length); \
1620 *sp++ = STRING_TO_JSVAL(str); \
1623 /* Push $&, $1, $2, ... */
1624 PUSH_REGEXP_STATIC(lastMatch
);
1626 m
= cx
->regExpStatics
.parenCount
;
1628 for (j
= 0; i
< n
; i
++, j
++)
1629 PUSH_REGEXP_STATIC(parens
[j
]);
1630 for (j
= 0; i
< m
; i
++, j
++)
1631 PUSH_REGEXP_STATIC(moreParens
[j
]);
1634 * We need to clear moreParens in the top-of-stack cx->regExpStatics
1635 * to it won't be possibly realloc'ed, leaving the bottom-of-stack
1636 * moreParens pointing to freed memory.
1638 cx
->regExpStatics
.moreParens
= NULL
;
1639 freeMoreParens
= JS_TRUE
;
1641 #undef PUSH_REGEXP_STATIC
1643 /* Make sure to push undefined for any unmatched parens. */
1647 /* Push match index and input string. */
1648 *sp
++ = INT_TO_JSVAL((jsint
)cx
->regExpStatics
.leftContext
.length
);
1649 *sp
++ = STRING_TO_JSVAL(rdata
->base
.str
);
1651 ok
= js_Invoke(cx
, argc
, invokevp
, 0);
1654 * NB: we count on the newborn string root to hold any string
1655 * created by this js_ValueToString that would otherwise be GC-
1656 * able, until we use rdata->repstr in do_replace.
1658 repstr
= js_ValueToString(cx
, *invokevp
);
1662 rdata
->repstr
= repstr
;
1663 *sizep
= JSSTRING_LENGTH(repstr
);
1668 js_FreeStack(cx
, mark
);
1670 JS_free(cx
, cx
->regExpStatics
.moreParens
);
1671 cx
->regExpStatics
= save
;
1675 repstr
= rdata
->repstr
;
1676 replen
= JSSTRING_LENGTH(repstr
);
1677 for (dp
= rdata
->dollar
, ep
= rdata
->dollarEnd
; dp
;
1678 dp
= js_strchr_limit(dp
, '$', ep
)) {
1679 sub
= interpret_dollar(cx
, dp
, ep
, rdata
, &skip
);
1681 replen
+= sub
->length
- skip
;
1692 do_replace(JSContext
*cx
, ReplaceData
*rdata
, jschar
*chars
)
1695 jschar
*bp
, *cp
, *dp
, *ep
;
1699 repstr
= rdata
->repstr
;
1700 bp
= cp
= JSSTRING_CHARS(repstr
);
1701 for (dp
= rdata
->dollar
, ep
= rdata
->dollarEnd
; dp
;
1702 dp
= js_strchr_limit(dp
, '$', ep
)) {
1704 js_strncpy(chars
, cp
, len
);
1707 sub
= interpret_dollar(cx
, dp
, ep
, rdata
, &skip
);
1710 js_strncpy(chars
, sub
->chars
, len
);
1718 js_strncpy(chars
, cp
, JSSTRING_LENGTH(repstr
) - (cp
- bp
));
1722 replace_destroy(JSContext
*cx
, GlobData
*data
)
1726 rdata
= (ReplaceData
*)data
;
1727 JS_free(cx
, rdata
->chars
);
1728 rdata
->chars
= NULL
;
1732 replace_glob(JSContext
*cx
, jsint count
, GlobData
*data
)
1736 size_t leftoff
, leftlen
, replen
, growth
;
1740 rdata
= (ReplaceData
*)data
;
1742 leftoff
= rdata
->leftIndex
;
1743 left
= JSSTRING_CHARS(str
) + leftoff
;
1744 leftlen
= cx
->regExpStatics
.lastMatch
.chars
- left
;
1745 rdata
->leftIndex
= cx
->regExpStatics
.lastMatch
.chars
- JSSTRING_CHARS(str
);
1746 rdata
->leftIndex
+= cx
->regExpStatics
.lastMatch
.length
;
1747 if (!find_replen(cx
, rdata
, &replen
))
1749 growth
= leftlen
+ replen
;
1752 ? JS_realloc(cx
, rdata
->chars
, (rdata
->length
+ growth
+ 1)
1754 : JS_malloc(cx
, (growth
+ 1) * sizeof(jschar
)));
1757 rdata
->chars
= chars
;
1758 rdata
->length
+= growth
;
1759 chars
+= rdata
->index
;
1760 rdata
->index
+= growth
;
1761 js_strncpy(chars
, left
, leftlen
);
1763 do_replace(cx
, rdata
, chars
);
1768 str_replace(JSContext
*cx
, uintN argc
, jsval
*vp
)
1773 if (argc
>= 2 && JS_TypeOfValue(cx
, vp
[3]) == JSTYPE_FUNCTION
) {
1774 lambda
= JSVAL_TO_OBJECT(vp
[3]);
1778 repstr
= ArgToRootedString(cx
, argc
, vp
, 1);
1783 return js_StringReplaceHelper(cx
, argc
, lambda
, repstr
, vp
);
1787 static JSString
* FASTCALL
1788 String_p_replace_str(JSContext
* cx
, JSString
* str
, JSObject
* regexp
, JSString
* repstr
)
1791 JSVAL_NULL
, STRING_TO_JSVAL(str
), OBJECT_TO_JSVAL(regexp
), STRING_TO_JSVAL(repstr
)
1793 if (!js_StringReplaceHelper(cx
, 2, NULL
, repstr
, vp
))
1795 JS_ASSERT(JSVAL_IS_STRING(vp
[0]));
1796 return JSVAL_TO_STRING(vp
[0]);
1799 static JSString
* FASTCALL
1800 String_p_replace_str2(JSContext
* cx
, JSString
* str
, JSString
* patstr
, JSString
* repstr
)
1803 JSVAL_NULL
, STRING_TO_JSVAL(str
), STRING_TO_JSVAL(patstr
), STRING_TO_JSVAL(repstr
)
1805 if (!js_StringReplaceHelper(cx
, 2, NULL
, repstr
, vp
))
1807 JS_ASSERT(JSVAL_IS_STRING(vp
[0]));
1808 return JSVAL_TO_STRING(vp
[0]);
1811 static JSString
* FASTCALL
1812 String_p_replace_str3(JSContext
* cx
, JSString
* str
, JSString
* patstr
, JSString
* repstr
,
1816 JSVAL_NULL
, STRING_TO_JSVAL(str
), STRING_TO_JSVAL(patstr
), STRING_TO_JSVAL(repstr
),
1817 STRING_TO_JSVAL(flagstr
)
1819 if (!js_StringReplaceHelper(cx
, 3, NULL
, repstr
, vp
))
1821 JS_ASSERT(JSVAL_IS_STRING(vp
[0]));
1822 return JSVAL_TO_STRING(vp
[0]);
1827 js_StringReplaceHelper(JSContext
*cx
, uintN argc
, JSObject
*lambda
,
1828 JSString
*repstr
, jsval
*vp
)
1832 size_t leftlen
, rightlen
, length
;
1837 * For ECMA Edition 3, the first argument is to be converted to a string
1838 * to match in a "flat" sense (without regular expression metachars having
1839 * special meanings) UNLESS the first arg is a RegExp object.
1841 rdata
.base
.flags
= MODE_REPLACE
| KEEP_REGEXP
| FORCE_FLAT
;
1842 rdata
.base
.optarg
= 2;
1844 rdata
.lambda
= lambda
;
1845 rdata
.repstr
= repstr
;
1847 rdata
.dollarEnd
= JSSTRING_CHARS(repstr
) + JSSTRING_LENGTH(repstr
);
1848 rdata
.dollar
= js_strchr_limit(JSSTRING_CHARS(repstr
), '$',
1851 rdata
.dollar
= rdata
.dollarEnd
= NULL
;
1856 rdata
.leftIndex
= 0;
1858 ok
= match_or_replace(cx
, replace_glob
, replace_destroy
, &rdata
.base
,
1864 if ((rdata
.base
.flags
& GLOBAL_REGEXP
) || *vp
!= JSVAL_TRUE
) {
1865 /* Didn't match even once. */
1866 *vp
= STRING_TO_JSVAL(rdata
.base
.str
);
1869 leftlen
= cx
->regExpStatics
.leftContext
.length
;
1870 ok
= find_replen(cx
, &rdata
, &length
);
1874 chars
= (jschar
*) JS_malloc(cx
, (length
+ 1) * sizeof(jschar
));
1879 js_strncpy(chars
, cx
->regExpStatics
.leftContext
.chars
, leftlen
);
1880 do_replace(cx
, &rdata
, chars
+ leftlen
);
1881 rdata
.chars
= chars
;
1882 rdata
.length
= length
;
1885 rightlen
= cx
->regExpStatics
.rightContext
.length
;
1886 length
= rdata
.length
+ rightlen
;
1888 JS_realloc(cx
, rdata
.chars
, (length
+ 1) * sizeof(jschar
));
1890 JS_free(cx
, rdata
.chars
);
1894 js_strncpy(chars
+ rdata
.length
, cx
->regExpStatics
.rightContext
.chars
,
1898 str
= js_NewString(cx
, chars
, length
);
1904 *vp
= STRING_TO_JSVAL(str
);
1907 /* If KEEP_REGEXP is still set, it's our job to destroy regexp now. */
1908 if (rdata
.base
.flags
& KEEP_REGEXP
)
1909 js_DestroyRegExp(cx
, rdata
.base
.regexp
);
1914 * Subroutine used by str_split to find the next split point in str, starting
1915 * at offset *ip and looking either for the separator substring given by sep, or
1916 * for the next re match. In the re case, return the matched separator in *sep,
1917 * and the possibly updated offset in *ip.
1919 * Return -2 on error, -1 on end of string, >= 0 for a valid index of the next
1920 * separator occurrence if found, or str->length if no separator is found.
1923 find_split(JSContext
*cx
, JSString
*str
, JSRegExp
*re
, jsint
*ip
,
1931 * Stop if past end of string. If at end of string, we will compare the
1932 * null char stored there (by js_NewString*) to sep->chars[j] in the while
1933 * loop at the end of this function, so that
1935 * "ab,".split(',') => ["ab", ""]
1937 * and the resulting array converts back to the string "ab," for symmetry.
1938 * However, we ape Perl and do this only if there is a sufficiently large
1939 * limit argument (see str_split).
1942 length
= JSSTRING_LENGTH(str
);
1943 if ((size_t)i
> length
)
1946 chars
= JSSTRING_CHARS(str
);
1949 * Match a regular expression against the separator at or above index i.
1950 * Call js_ExecuteRegExp with true for the test argument. On successful
1951 * match, get the separator from cx->regExpStatics.lastMatch.
1958 /* JS1.2 deviated from Perl by never matching at end of string. */
1960 if (!js_ExecuteRegExp(cx
, re
, str
, &index
, JS_TRUE
, &rval
))
1962 if (rval
!= JSVAL_TRUE
) {
1963 /* Mismatch: ensure our caller advances i past end of string. */
1968 *sep
= cx
->regExpStatics
.lastMatch
;
1969 if (sep
->length
== 0) {
1971 * Empty string match: never split on an empty match at the start
1972 * of a find_split cycle. Same rule as for an empty global match
1973 * in match_or_replace.
1977 * "Bump-along" to avoid sticking at an empty match, but don't
1978 * bump past end of string -- our caller must do that by adding
1979 * sep->length to our return value.
1981 if ((size_t)i
== length
)
1986 if ((size_t)i
== length
) {
1988 * If there was a trivial zero-length match at the end of the
1989 * split, then we shouldn't output the matched string at the end
1990 * of the split array. See ECMA-262 Ed. 3, 15.5.4.14, Step 15.
1995 JS_ASSERT((size_t)i
>= sep
->length
);
1996 return i
- sep
->length
;
2000 * Special case: if sep is the empty string, split str into one character
2001 * substrings. Let our caller worry about whether to split once at end of
2002 * string into an empty substring.
2004 if (sep
->length
== 0)
2005 return ((size_t)i
== length
) ? -1 : i
+ 1;
2008 * Now that we know sep is non-empty, search starting at i in str for an
2009 * occurrence of all of sep's chars. If we find them, return the index of
2010 * the first separator char. Otherwise, return length.
2013 while ((size_t)(k
= i
+ j
) < length
) {
2014 if (chars
[k
] == sep
->chars
[j
]) {
2015 if ((size_t)++j
== sep
->length
)
2026 str_split(JSContext
*cx
, uintN argc
, jsval
*vp
)
2028 JSString
*str
, *sub
;
2033 JSSubString
*sep
, tmp
;
2038 NORMALIZE_THIS(cx
, vp
, str
);
2040 arrayobj
= js_NewArrayObject(cx
, 0, NULL
);
2043 *vp
= OBJECT_TO_JSVAL(arrayobj
);
2046 v
= STRING_TO_JSVAL(str
);
2047 ok
= OBJ_SET_PROPERTY(cx
, arrayobj
, INT_TO_JSID(0), &v
);
2049 if (VALUE_IS_REGEXP(cx
, vp
[2])) {
2050 re
= (JSRegExp
*) JS_GetPrivate(cx
, JSVAL_TO_OBJECT(vp
[2]));
2053 /* Set a magic value so we can detect a successful re match. */
2057 JSString
*str2
= js_ValueToString(cx
, vp
[2]);
2060 vp
[2] = STRING_TO_JSVAL(str2
);
2063 * Point sep at a local copy of str2's header because find_split
2064 * will modify sep->length.
2066 JSSTRING_CHARS_AND_LENGTH(str2
, tmp
.chars
, tmp
.length
);
2071 /* Use the second argument as the split limit, if given. */
2072 limited
= (argc
> 1) && !JSVAL_IS_VOID(vp
[3]);
2073 limit
= 0; /* Avoid warning. */
2075 d
= js_ValueToNumber(cx
, &vp
[3]);
2076 if (JSVAL_IS_NULL(vp
[3]))
2079 /* Clamp limit between 0 and 1 + string length. */
2080 limit
= js_DoubleToECMAUint32(d
);
2081 if (limit
> JSSTRING_LENGTH(str
))
2082 limit
= 1 + JSSTRING_LENGTH(str
);
2086 while ((j
= find_split(cx
, str
, re
, &i
, sep
)) >= 0) {
2087 if (limited
&& len
>= limit
)
2089 sub
= js_NewDependentString(cx
, str
, i
, (size_t)(j
- i
));
2092 v
= STRING_TO_JSVAL(sub
);
2093 if (!JS_SetElement(cx
, arrayobj
, len
, &v
))
2098 * Imitate perl's feature of including parenthesized substrings
2099 * that matched part of the delimiter in the new array, after the
2100 * split substring that was delimited.
2102 if (re
&& sep
->chars
) {
2104 JSSubString
*parsub
;
2106 for (num
= 0; num
< cx
->regExpStatics
.parenCount
; num
++) {
2107 if (limited
&& len
>= limit
)
2109 parsub
= REGEXP_PAREN_SUBSTRING(&cx
->regExpStatics
, num
);
2110 sub
= js_NewStringCopyN(cx
, parsub
->chars
, parsub
->length
);
2113 v
= STRING_TO_JSVAL(sub
);
2114 if (!JS_SetElement(cx
, arrayobj
, len
, &v
))
2120 i
= j
+ sep
->length
;
2128 static JSObject
* FASTCALL
2129 String_p_split(JSContext
* cx
, JSString
* str
, JSString
* sepstr
)
2131 // FIXME: Avoid building and then parsing this array.
2132 jsval vp
[4] = { JSVAL_NULL
, STRING_TO_JSVAL(str
), STRING_TO_JSVAL(sepstr
), JSVAL_VOID
};
2133 if (!str_split(cx
, 2, vp
))
2135 JS_ASSERT(JSVAL_IS_OBJECT(vp
[0]));
2136 return JSVAL_TO_OBJECT(vp
[0]);
2140 #if JS_HAS_PERL_SUBSTR
2142 str_substr(JSContext
*cx
, uintN argc
, jsval
*vp
)
2146 jsdouble length
, begin
, end
;
2148 NORMALIZE_THIS(cx
, vp
, str
);
2150 d
= js_ValueToNumber(cx
, &vp
[2]);
2151 if (JSVAL_IS_NULL(vp
[2]))
2153 length
= JSSTRING_LENGTH(str
);
2154 begin
= js_DoubleToInteger(d
);
2159 } else if (begin
> length
) {
2166 d
= js_ValueToNumber(cx
, &vp
[3]);
2167 if (JSVAL_IS_NULL(vp
[3]))
2169 end
= js_DoubleToInteger(d
);
2177 str
= js_NewDependentString(cx
, str
,
2179 (size_t)(end
- begin
));
2183 *vp
= STRING_TO_JSVAL(str
);
2186 #endif /* JS_HAS_PERL_SUBSTR */
2189 * Python-esque sequence operations.
2192 str_concat(JSContext
*cx
, uintN argc
, jsval
*vp
)
2194 JSString
*str
, *str2
;
2198 NORMALIZE_THIS(cx
, vp
, str
);
2200 for (i
= 0, argv
= vp
+ 2; i
< argc
; i
++) {
2201 str2
= js_ValueToString(cx
, argv
[i
]);
2204 argv
[i
] = STRING_TO_JSVAL(str2
);
2206 str
= js_ConcatStrings(cx
, str
, str2
);
2211 *vp
= STRING_TO_JSVAL(str
);
2216 static JSString
* FASTCALL
2217 String_p_concat_1int(JSContext
* cx
, JSString
* str
, int32 i
)
2219 // FIXME: should be able to use stack buffer and avoid istr...
2220 JSString
* istr
= js_NumberToString(cx
, i
);
2223 return js_ConcatStrings(cx
, str
, istr
);
2226 static JSString
* FASTCALL
2227 String_p_concat_2str(JSContext
* cx
, JSString
* str
, JSString
* a
, JSString
* b
)
2229 str
= js_ConcatStrings(cx
, str
, a
);
2231 return js_ConcatStrings(cx
, str
, b
);
2235 static JSString
* FASTCALL
2236 String_p_concat_3str(JSContext
* cx
, JSString
* str
, JSString
* a
, JSString
* b
, JSString
* c
)
2238 str
= js_ConcatStrings(cx
, str
, a
);
2240 str
= js_ConcatStrings(cx
, str
, b
);
2242 return js_ConcatStrings(cx
, str
, c
);
2249 str_slice(JSContext
*cx
, uintN argc
, jsval
*vp
)
2256 if (argc
== 1 && JSVAL_IS_STRING(t
) && JSVAL_IS_INT(v
)) {
2257 size_t begin
, end
, length
;
2259 str
= JSVAL_TO_STRING(t
);
2260 begin
= JSVAL_TO_INT(v
);
2261 end
= JSSTRING_LENGTH(str
);
2263 length
= end
- begin
;
2265 str
= cx
->runtime
->emptyString
;
2268 ? js_GetUnitString(cx
, str
, begin
)
2269 : js_NewDependentString(cx
, str
, begin
, length
);
2273 *vp
= STRING_TO_JSVAL(str
);
2278 NORMALIZE_THIS(cx
, vp
, str
);
2281 double begin
, end
, length
;
2283 begin
= js_ValueToNumber(cx
, &vp
[2]);
2284 if (JSVAL_IS_NULL(vp
[2]))
2286 begin
= js_DoubleToInteger(begin
);
2287 length
= JSSTRING_LENGTH(str
);
2292 } else if (begin
> length
) {
2299 end
= js_ValueToNumber(cx
, &vp
[3]);
2300 if (JSVAL_IS_NULL(vp
[3]))
2302 end
= js_DoubleToInteger(end
);
2307 } else if (end
> length
) {
2314 str
= js_NewDependentString(cx
, str
,
2316 (size_t)(end
- begin
));
2320 *vp
= STRING_TO_JSVAL(str
);
2324 #if JS_HAS_STR_HTML_HELPERS
2326 * HTML composition aids.
2329 tagify(JSContext
*cx
, const char *begin
, JSString
*param
, const char *end
,
2334 size_t beglen
, endlen
, parlen
, taglen
;
2337 NORMALIZE_THIS(cx
, vp
, str
);
2342 beglen
= strlen(begin
);
2343 taglen
= 1 + beglen
+ 1; /* '<begin' + '>' */
2344 parlen
= 0; /* Avoid warning. */
2346 parlen
= JSSTRING_LENGTH(param
);
2347 taglen
+= 2 + parlen
+ 1; /* '="param"' */
2349 endlen
= strlen(end
);
2350 taglen
+= JSSTRING_LENGTH(str
) + 2 + endlen
+ 1; /* 'str</end>' */
2352 if (taglen
>= ~(size_t)0 / sizeof(jschar
)) {
2353 js_ReportAllocationOverflow(cx
);
2357 tagbuf
= (jschar
*) JS_malloc(cx
, (taglen
+ 1) * sizeof(jschar
));
2363 for (i
= 0; i
< beglen
; i
++)
2364 tagbuf
[j
++] = (jschar
)begin
[i
];
2368 js_strncpy(&tagbuf
[j
], JSSTRING_CHARS(param
), parlen
);
2373 js_strncpy(&tagbuf
[j
], JSSTRING_CHARS(str
), JSSTRING_LENGTH(str
));
2374 j
+= JSSTRING_LENGTH(str
);
2377 for (i
= 0; i
< endlen
; i
++)
2378 tagbuf
[j
++] = (jschar
)end
[i
];
2380 JS_ASSERT(j
== taglen
);
2383 str
= js_NewString(cx
, tagbuf
, taglen
);
2385 free((char *)tagbuf
);
2388 *vp
= STRING_TO_JSVAL(str
);
2393 tagify_value(JSContext
*cx
, uintN argc
, jsval
*vp
,
2394 const char *begin
, const char *end
)
2398 param
= ArgToRootedString(cx
, argc
, vp
, 0);
2401 return tagify(cx
, begin
, param
, end
, vp
);
2405 str_bold(JSContext
*cx
, uintN argc
, jsval
*vp
)
2407 return tagify(cx
, "b", NULL
, NULL
, vp
);
2411 str_italics(JSContext
*cx
, uintN argc
, jsval
*vp
)
2413 return tagify(cx
, "i", NULL
, NULL
, vp
);
2417 str_fixed(JSContext
*cx
, uintN argc
, jsval
*vp
)
2419 return tagify(cx
, "tt", NULL
, NULL
, vp
);
2423 str_fontsize(JSContext
*cx
, uintN argc
, jsval
*vp
)
2425 return tagify_value(cx
, argc
, vp
, "font size", "font");
2429 str_fontcolor(JSContext
*cx
, uintN argc
, jsval
*vp
)
2431 return tagify_value(cx
, argc
, vp
, "font color", "font");
2435 str_link(JSContext
*cx
, uintN argc
, jsval
*vp
)
2437 return tagify_value(cx
, argc
, vp
, "a href", "a");
2441 str_anchor(JSContext
*cx
, uintN argc
, jsval
*vp
)
2443 return tagify_value(cx
, argc
, vp
, "a name", "a");
2447 str_strike(JSContext
*cx
, uintN argc
, jsval
*vp
)
2449 return tagify(cx
, "strike", NULL
, NULL
, vp
);
2453 str_small(JSContext
*cx
, uintN argc
, jsval
*vp
)
2455 return tagify(cx
, "small", NULL
, NULL
, vp
);
2459 str_big(JSContext
*cx
, uintN argc
, jsval
*vp
)
2461 return tagify(cx
, "big", NULL
, NULL
, vp
);
2465 str_blink(JSContext
*cx
, uintN argc
, jsval
*vp
)
2467 return tagify(cx
, "blink", NULL
, NULL
, vp
);
2471 str_sup(JSContext
*cx
, uintN argc
, jsval
*vp
)
2473 return tagify(cx
, "sup", NULL
, NULL
, vp
);
2477 str_sub(JSContext
*cx
, uintN argc
, jsval
*vp
)
2479 return tagify(cx
, "sub", NULL
, NULL
, vp
);
2481 #endif /* JS_HAS_STR_HTML_HELPERS */
2485 js_String_getelem(JSContext
* cx
, JSString
* str
, int32 i
)
2487 if ((size_t)i
>= JSSTRING_LENGTH(str
))
2489 return js_GetUnitString(cx
, str
, (size_t)i
);
2493 JS_DEFINE_CALLINFO_2(extern, BOOL
, js_EqualStrings
, STRING
, STRING
, 1, 1)
2494 JS_DEFINE_CALLINFO_2(extern, INT32
, js_CompareStrings
, STRING
, STRING
, 1, 1)
2496 JS_DEFINE_TRCINFO_1(str_toString
,
2497 (2, (extern, STRING_FAIL
, String_p_toString
, CONTEXT
, THIS
, 1, 1)))
2498 JS_DEFINE_TRCINFO_2(str_substring
,
2499 (4, (static, STRING_FAIL
, String_p_substring
, CONTEXT
, THIS_STRING
, INT32
, INT32
, 1, 1)),
2500 (3, (static, STRING_FAIL
, String_p_substring_1
, CONTEXT
, THIS_STRING
, INT32
, 1, 1)))
2501 JS_DEFINE_TRCINFO_1(str_charAt
,
2502 (3, (extern, STRING_FAIL
, js_String_getelem
, CONTEXT
, THIS_STRING
, INT32
, 1, 1)))
2503 JS_DEFINE_TRCINFO_1(str_charCodeAt
,
2504 (2, (extern, INT32_FAIL
, js_String_p_charCodeAt
, THIS_STRING
, INT32
, 1, 1)))
2505 JS_DEFINE_TRCINFO_4(str_concat
,
2506 (3, (static, STRING_FAIL
, String_p_concat_1int
, CONTEXT
, THIS_STRING
, INT32
, 1, 1)),
2507 (3, (extern, STRING_FAIL
, js_ConcatStrings
, CONTEXT
, THIS_STRING
, STRING
, 1, 1)),
2508 (4, (static, STRING_FAIL
, String_p_concat_2str
, CONTEXT
, THIS_STRING
, STRING
, STRING
, 1, 1)),
2509 (5, (static, STRING_FAIL
, String_p_concat_3str
, CONTEXT
, THIS_STRING
, STRING
, STRING
, STRING
, 1, 1)))
2510 JS_DEFINE_TRCINFO_2(str_match
,
2511 (4, (static, OBJECT_FAIL_VOID
, String_p_match
, CONTEXT
, THIS_STRING
, PC
, REGEXP
, 1, 1)),
2512 (4, (static, OBJECT_FAIL_VOID
, String_p_match_obj
, CONTEXT
, THIS
, PC
, REGEXP
, 1, 1)))
2513 JS_DEFINE_TRCINFO_3(str_replace
,
2514 (4, (static, STRING_FAIL
, String_p_replace_str
, CONTEXT
, THIS_STRING
, REGEXP
, STRING
, 1, 1)),
2515 (4, (static, STRING_FAIL
, String_p_replace_str2
, CONTEXT
, THIS_STRING
, STRING
, STRING
, 1, 1)),
2516 (5, (static, STRING_FAIL
, String_p_replace_str3
, CONTEXT
, THIS_STRING
, STRING
, STRING
, STRING
, 1, 1)))
2517 JS_DEFINE_TRCINFO_1(str_split
,
2518 (3, (static, OBJECT_FAIL_NULL
, String_p_split
, CONTEXT
, THIS_STRING
, STRING
, 0, 0)))
2519 JS_DEFINE_TRCINFO_1(str_toLowerCase
,
2520 (2, (extern, STRING_FAIL
, js_toLowerCase
, CONTEXT
, THIS_STRING
, 1, 1)))
2521 JS_DEFINE_TRCINFO_1(str_toUpperCase
,
2522 (2, (extern, STRING_FAIL
, js_toUpperCase
, CONTEXT
, THIS_STRING
, 1, 1)))
2524 #define GENERIC JSFUN_GENERIC_NATIVE
2525 #define PRIMITIVE JSFUN_THISP_PRIMITIVE
2526 #define GENERIC_PRIMITIVE (GENERIC | PRIMITIVE)
2528 static JSFunctionSpec string_methods
[] = {
2530 JS_FN("quote", str_quote
, 0,GENERIC_PRIMITIVE
),
2531 JS_FN(js_toSource_str
, str_toSource
, 0,JSFUN_THISP_STRING
),
2534 /* Java-like methods. */
2535 JS_TN(js_toString_str
, str_toString
, 0,JSFUN_THISP_STRING
, str_toString_trcinfo
),
2536 JS_FN(js_valueOf_str
, str_toString
, 0,JSFUN_THISP_STRING
),
2537 JS_FN(js_toJSON_str
, str_toString
, 0,JSFUN_THISP_STRING
),
2538 JS_TN("substring", str_substring
, 2,GENERIC_PRIMITIVE
, str_substring_trcinfo
),
2539 JS_TN("toLowerCase", str_toLowerCase
, 0,GENERIC_PRIMITIVE
, str_toLowerCase_trcinfo
),
2540 JS_TN("toUpperCase", str_toUpperCase
, 0,GENERIC_PRIMITIVE
, str_toUpperCase_trcinfo
),
2541 JS_TN("charAt", str_charAt
, 1,GENERIC_PRIMITIVE
, str_charAt_trcinfo
),
2542 JS_TN("charCodeAt", str_charCodeAt
, 1,GENERIC_PRIMITIVE
, str_charCodeAt_trcinfo
),
2543 JS_FN("indexOf", str_indexOf
, 1,GENERIC_PRIMITIVE
),
2544 JS_FN("lastIndexOf", str_lastIndexOf
, 1,GENERIC_PRIMITIVE
),
2545 JS_FN("trim", str_trim
, 0,GENERIC_PRIMITIVE
),
2546 JS_FN("trimLeft", str_trimLeft
, 0,GENERIC_PRIMITIVE
),
2547 JS_FN("trimRight", str_trimRight
, 0,GENERIC_PRIMITIVE
),
2548 JS_FN("toLocaleLowerCase", str_toLocaleLowerCase
, 0,GENERIC_PRIMITIVE
),
2549 JS_FN("toLocaleUpperCase", str_toLocaleUpperCase
, 0,GENERIC_PRIMITIVE
),
2550 JS_FN("localeCompare", str_localeCompare
, 1,GENERIC_PRIMITIVE
),
2552 /* Perl-ish methods (search is actually Python-esque). */
2553 JS_TN("match", str_match
, 1,GENERIC_PRIMITIVE
, str_match_trcinfo
),
2554 JS_FN("search", str_search
, 1,GENERIC_PRIMITIVE
),
2555 JS_TN("replace", str_replace
, 2,GENERIC_PRIMITIVE
, str_replace_trcinfo
),
2556 JS_TN("split", str_split
, 2,GENERIC_PRIMITIVE
, str_split_trcinfo
),
2557 #if JS_HAS_PERL_SUBSTR
2558 JS_FN("substr", str_substr
, 2,GENERIC_PRIMITIVE
),
2561 /* Python-esque sequence methods. */
2562 JS_TN("concat", str_concat
, 1,GENERIC_PRIMITIVE
, str_concat_trcinfo
),
2563 JS_FN("slice", str_slice
, 2,GENERIC_PRIMITIVE
),
2565 /* HTML string methods. */
2566 #if JS_HAS_STR_HTML_HELPERS
2567 JS_FN("bold", str_bold
, 0,PRIMITIVE
),
2568 JS_FN("italics", str_italics
, 0,PRIMITIVE
),
2569 JS_FN("fixed", str_fixed
, 0,PRIMITIVE
),
2570 JS_FN("fontsize", str_fontsize
, 1,PRIMITIVE
),
2571 JS_FN("fontcolor", str_fontcolor
, 1,PRIMITIVE
),
2572 JS_FN("link", str_link
, 1,PRIMITIVE
),
2573 JS_FN("anchor", str_anchor
, 1,PRIMITIVE
),
2574 JS_FN("strike", str_strike
, 0,PRIMITIVE
),
2575 JS_FN("small", str_small
, 0,PRIMITIVE
),
2576 JS_FN("big", str_big
, 0,PRIMITIVE
),
2577 JS_FN("blink", str_blink
, 0,PRIMITIVE
),
2578 JS_FN("sup", str_sup
, 0,PRIMITIVE
),
2579 JS_FN("sub", str_sub
, 0,PRIMITIVE
),
2586 String(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
2591 str
= js_ValueToString(cx
, argv
[0]);
2594 argv
[0] = STRING_TO_JSVAL(str
);
2596 str
= cx
->runtime
->emptyString
;
2598 if (!JS_IsConstructing(cx
)) {
2599 *rval
= STRING_TO_JSVAL(str
);
2602 STOBJ_SET_SLOT(obj
, JSSLOT_PRIVATE
, STRING_TO_JSVAL(str
));
2607 str_fromCharCode(JSContext
*cx
, uintN argc
, jsval
*vp
)
2616 JS_ASSERT(argc
< ARRAY_INIT_LIMIT
);
2618 (code
= js_ValueToUint16(cx
, &argv
[0])) < UNIT_STRING_LIMIT
) {
2619 str
= js_GetUnitStringForChar(cx
, code
);
2622 *vp
= STRING_TO_JSVAL(str
);
2625 chars
= (jschar
*) JS_malloc(cx
, (argc
+ 1) * sizeof(jschar
));
2628 for (i
= 0; i
< argc
; i
++) {
2629 code
= js_ValueToUint16(cx
, &argv
[i
]);
2630 if (JSVAL_IS_NULL(argv
[i
])) {
2634 chars
[i
] = (jschar
)code
;
2637 str
= js_NewString(cx
, chars
, argc
);
2642 *vp
= STRING_TO_JSVAL(str
);
2647 static JSString
* FASTCALL
2648 String_fromCharCode(JSContext
* cx
, int32 i
)
2650 JS_ASSERT(JS_ON_TRACE(cx
));
2651 jschar c
= (jschar
)i
;
2652 if (c
< UNIT_STRING_LIMIT
)
2653 return js_GetUnitStringForChar(cx
, c
);
2654 return js_NewStringCopyN(cx
, &c
, 1);
2658 JS_DEFINE_TRCINFO_1(str_fromCharCode
,
2659 (2, (static, STRING_FAIL
, String_fromCharCode
, CONTEXT
, INT32
, 1, 1)))
2661 static JSFunctionSpec string_static_methods
[] = {
2662 JS_TN("fromCharCode", str_fromCharCode
, 1, 0, str_fromCharCode_trcinfo
),
2667 js_hash_string_pointer(const void *key
)
2669 return (JSHashNumber
)JS_PTR_TO_UINT32(key
) >> JSVAL_TAGBITS
;
2673 js_InitRuntimeStringState(JSContext
*cx
)
2678 rt
->emptyString
= ATOM_TO_STRING(rt
->atomState
.emptyAtom
);
2683 js_InitDeflatedStringCache(JSRuntime
*rt
)
2687 /* Initialize string cache */
2688 JS_ASSERT(!rt
->deflatedStringCache
);
2689 cache
= JS_NewHashTable(8, js_hash_string_pointer
,
2690 JS_CompareValues
, JS_CompareValues
,
2694 rt
->deflatedStringCache
= cache
;
2696 #ifdef JS_THREADSAFE
2697 JS_ASSERT(!rt
->deflatedStringCacheLock
);
2698 rt
->deflatedStringCacheLock
= JS_NEW_LOCK();
2699 if (!rt
->deflatedStringCacheLock
)
2705 #define UNIT_STRING_SPACE(sp) ((jschar *) ((sp) + UNIT_STRING_LIMIT))
2706 #define UNIT_STRING_SPACE_RT(rt) UNIT_STRING_SPACE((rt)->unitStrings)
2708 #define IN_UNIT_STRING_SPACE(sp,cp) \
2709 ((size_t)((cp) - UNIT_STRING_SPACE(sp)) < 2 * UNIT_STRING_LIMIT)
2710 #define IN_UNIT_STRING_SPACE_RT(rt,cp) \
2711 IN_UNIT_STRING_SPACE((rt)->unitStrings, cp)
2714 js_GetUnitStringForChar(JSContext
*cx
, jschar c
)
2720 JS_ASSERT(c
< UNIT_STRING_LIMIT
);
2722 if (!rt
->unitStrings
) {
2723 sp
= (JSString
**) calloc(UNIT_STRING_LIMIT
* sizeof(JSString
*) +
2724 UNIT_STRING_LIMIT
* 2 * sizeof(jschar
),
2727 JS_ReportOutOfMemory(cx
);
2730 cp
= UNIT_STRING_SPACE(sp
);
2731 for (i
= 0; i
< UNIT_STRING_LIMIT
; i
++) {
2736 if (!rt
->unitStrings
) {
2737 rt
->unitStrings
= sp
;
2744 if (!rt
->unitStrings
[c
]) {
2747 cp
= UNIT_STRING_SPACE_RT(rt
);
2748 str
= js_NewString(cx
, cp
+ 2 * c
, 1);
2752 if (!rt
->unitStrings
[c
])
2753 rt
->unitStrings
[c
] = str
;
2756 return rt
->unitStrings
[c
];
2760 js_GetUnitString(JSContext
*cx
, JSString
*str
, size_t index
)
2764 JS_ASSERT(index
< JSSTRING_LENGTH(str
));
2765 c
= JSSTRING_CHARS(str
)[index
];
2766 if (c
>= UNIT_STRING_LIMIT
)
2767 return js_NewDependentString(cx
, str
, index
, 1);
2768 return js_GetUnitStringForChar(cx
, c
);
2772 js_FinishUnitStrings(JSRuntime
*rt
)
2774 free(rt
->unitStrings
);
2775 rt
->unitStrings
= NULL
;
2779 js_FinishRuntimeStringState(JSContext
*cx
)
2781 cx
->runtime
->emptyString
= NULL
;
2785 js_FinishDeflatedStringCache(JSRuntime
*rt
)
2787 if (rt
->deflatedStringCache
) {
2788 JS_HashTableDestroy(rt
->deflatedStringCache
);
2789 rt
->deflatedStringCache
= NULL
;
2791 #ifdef JS_THREADSAFE
2792 if (rt
->deflatedStringCacheLock
) {
2793 JS_DESTROY_LOCK(rt
->deflatedStringCacheLock
);
2794 rt
->deflatedStringCacheLock
= NULL
;
2800 js_InitStringClass(JSContext
*cx
, JSObject
*obj
)
2804 /* Define the escape, unescape functions in the global object. */
2805 if (!JS_DefineFunctions(cx
, obj
, string_functions
))
2808 proto
= JS_InitClass(cx
, obj
, NULL
, &js_StringClass
, String
, 1,
2809 string_props
, string_methods
,
2810 NULL
, string_static_methods
);
2813 STOBJ_SET_SLOT(proto
, JSSLOT_PRIVATE
,
2814 STRING_TO_JSVAL(cx
->runtime
->emptyString
));
2819 js_NewString(JSContext
*cx
, jschar
*chars
, size_t length
)
2823 if (length
> JSSTRING_LENGTH_MASK
) {
2824 js_ReportAllocationOverflow(cx
);
2828 str
= (JSString
*) js_NewGCThing(cx
, GCX_STRING
, sizeof(JSString
));
2831 JSFLATSTR_INIT(str
, chars
, length
);
2834 JSRuntime
*rt
= cx
->runtime
;
2835 JS_RUNTIME_METER(rt
, liveStrings
);
2836 JS_RUNTIME_METER(rt
, totalStrings
);
2837 JS_LOCK_RUNTIME_VOID(rt
,
2838 (rt
->lengthSum
+= (double)length
,
2839 rt
->lengthSquaredSum
+= (double)length
* (double)length
));
2846 js_NewDependentString(JSContext
*cx
, JSString
*base
, size_t start
,
2852 return cx
->runtime
->emptyString
;
2854 if (start
== 0 && length
== JSSTRING_LENGTH(base
))
2857 if (start
> JSSTRDEP_START_MASK
||
2858 (start
!= 0 && length
> JSSTRDEP_LENGTH_MASK
)) {
2859 return js_NewStringCopyN(cx
, JSSTRING_CHARS(base
) + start
, length
);
2862 ds
= (JSString
*)js_NewGCThing(cx
, GCX_STRING
, sizeof(JSString
));
2866 JSPREFIX_INIT(ds
, base
, length
);
2868 JSSTRDEP_INIT(ds
, base
, start
, length
);
2871 JSRuntime
*rt
= cx
->runtime
;
2872 JS_RUNTIME_METER(rt
, liveDependentStrings
);
2873 JS_RUNTIME_METER(rt
, totalDependentStrings
);
2874 JS_RUNTIME_METER(rt
, liveStrings
);
2875 JS_RUNTIME_METER(rt
, totalStrings
);
2876 JS_LOCK_RUNTIME_VOID(rt
,
2877 (rt
->strdepLengthSum
+= (double)length
,
2878 rt
->strdepLengthSquaredSum
+= (double)length
* (double)length
));
2879 JS_LOCK_RUNTIME_VOID(rt
,
2880 (rt
->lengthSum
+= (double)length
,
2881 rt
->lengthSquaredSum
+= (double)length
* (double)length
));
2890 void printJSStringStats(JSRuntime
*rt
)
2894 mean
= JS_MeanAndStdDev(rt
->totalStrings
, rt
->lengthSum
,
2895 rt
->lengthSquaredSum
, &sigma
);
2897 fprintf(stderr
, "%lu total strings, mean length %g (sigma %g)\n",
2898 (unsigned long)rt
->totalStrings
, mean
, sigma
);
2900 mean
= JS_MeanAndStdDev(rt
->totalDependentStrings
, rt
->strdepLengthSum
,
2901 rt
->strdepLengthSquaredSum
, &sigma
);
2903 fprintf(stderr
, "%lu total dependent strings, mean length %g (sigma %g)\n",
2904 (unsigned long)rt
->totalDependentStrings
, mean
, sigma
);
2909 js_NewStringCopyN(JSContext
*cx
, const jschar
*s
, size_t n
)
2914 news
= (jschar
*) JS_malloc(cx
, (n
+ 1) * sizeof(jschar
));
2917 js_strncpy(news
, s
, n
);
2919 str
= js_NewString(cx
, news
, n
);
2926 js_NewStringCopyZ(JSContext
*cx
, const jschar
*s
)
2933 m
= (n
+ 1) * sizeof(jschar
);
2934 news
= (jschar
*) JS_malloc(cx
, m
);
2938 str
= js_NewString(cx
, news
, n
);
2945 js_PurgeDeflatedStringCache(JSRuntime
*rt
, JSString
*str
)
2948 JSHashEntry
*he
, **hep
;
2950 hash
= js_hash_string_pointer(str
);
2951 JS_ACQUIRE_LOCK(rt
->deflatedStringCacheLock
);
2952 hep
= JS_HashTableRawLookup(rt
->deflatedStringCache
, hash
, str
);
2956 rt
->deflatedStringCacheBytes
-= JSSTRING_LENGTH(str
);
2959 JS_HashTableRawRemove(rt
->deflatedStringCache
, hep
, he
);
2961 JS_RELEASE_LOCK(rt
->deflatedStringCacheLock
);
2964 static JSStringFinalizeOp str_finalizers
[GCX_NTYPES
- GCX_EXTERNAL_STRING
] = {
2965 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
2969 js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop
,
2970 JSStringFinalizeOp newop
)
2974 for (i
= 0; i
!= JS_ARRAY_LENGTH(str_finalizers
); i
++) {
2975 if (str_finalizers
[i
] == oldop
) {
2976 str_finalizers
[i
] = newop
;
2984 * cx is NULL when we are called from js_FinishAtomState to force the
2985 * finalization of the permanently interned strings.
2988 js_FinalizeStringRT(JSRuntime
*rt
, JSString
*str
, intN type
, JSContext
*cx
)
2992 JSStringFinalizeOp finalizer
;
2994 JS_RUNTIME_UNMETER(rt
, liveStrings
);
2995 if (JSSTRING_IS_DEPENDENT(str
)) {
2996 /* A dependent string can not be external and must be valid. */
2997 JS_ASSERT(type
< 0);
2998 JS_ASSERT(JSSTRDEP_BASE(str
));
2999 JS_RUNTIME_UNMETER(rt
, liveDependentStrings
);
3002 /* A stillborn string has null chars, so is not valid. */
3003 chars
= JSFLATSTR_CHARS(str
);
3004 valid
= (chars
!= NULL
);
3006 if (IN_UNIT_STRING_SPACE_RT(rt
, chars
)) {
3007 JS_ASSERT(rt
->unitStrings
[*chars
] == str
);
3008 JS_ASSERT(type
< 0);
3009 rt
->unitStrings
[*chars
] = NULL
;
3010 } else if (type
< 0) {
3013 JS_ASSERT((uintN
) type
< JS_ARRAY_LENGTH(str_finalizers
));
3014 finalizer
= str_finalizers
[type
];
3017 * Assume that the finalizer for the permanently interned
3018 * string knows how to deal with null context.
3026 js_PurgeDeflatedStringCache(rt
, str
);
3029 JS_FRIEND_API(const char *)
3030 js_ValueToPrintable(JSContext
*cx
, jsval v
, JSValueToStringFun v2sfun
)
3034 str
= v2sfun(cx
, v
);
3037 str
= js_QuoteString(cx
, str
, 0);
3040 return js_GetStringBytes(cx
, str
);
3043 JS_FRIEND_API(JSString
*)
3044 js_ValueToString(JSContext
*cx
, jsval v
)
3049 if (JSVAL_IS_OBJECT(v
)) {
3050 obj
= JSVAL_TO_OBJECT(v
);
3052 return ATOM_TO_STRING(cx
->runtime
->atomState
.nullAtom
);
3053 if (!OBJ_DEFAULT_VALUE(cx
, obj
, JSTYPE_STRING
, &v
))
3056 if (JSVAL_IS_STRING(v
)) {
3057 str
= JSVAL_TO_STRING(v
);
3058 } else if (JSVAL_IS_INT(v
)) {
3059 str
= js_NumberToString(cx
, JSVAL_TO_INT(v
));
3060 } else if (JSVAL_IS_DOUBLE(v
)) {
3061 str
= js_NumberToString(cx
, *JSVAL_TO_DOUBLE(v
));
3062 } else if (JSVAL_IS_BOOLEAN(v
)) {
3063 str
= js_BooleanToString(cx
, JSVAL_TO_BOOLEAN(v
));
3065 str
= ATOM_TO_STRING(cx
->runtime
->atomState
.typeAtoms
[JSTYPE_VOID
]);
3070 JS_FRIEND_API(JSString
*)
3071 js_ValueToSource(JSContext
*cx
, jsval v
)
3073 JSTempValueRooter tvr
;
3076 if (JSVAL_IS_VOID(v
))
3077 return ATOM_TO_STRING(cx
->runtime
->atomState
.void0Atom
);
3078 if (JSVAL_IS_STRING(v
))
3079 return js_QuoteString(cx
, JSVAL_TO_STRING(v
), '"');
3080 if (JSVAL_IS_PRIMITIVE(v
)) {
3081 /* Special case to preserve negative zero, _contra_ toString. */
3082 if (JSVAL_IS_DOUBLE(v
) && JSDOUBLE_IS_NEGZERO(*JSVAL_TO_DOUBLE(v
))) {
3083 /* NB: _ucNstr rather than _ucstr to indicate non-terminated. */
3084 static const jschar js_negzero_ucNstr
[] = {'-', '0'};
3086 return js_NewStringCopyN(cx
, js_negzero_ucNstr
, 2);
3088 return js_ValueToString(cx
, v
);
3091 JS_PUSH_SINGLE_TEMP_ROOT(cx
, JSVAL_NULL
, &tvr
);
3092 if (!js_TryMethod(cx
, JSVAL_TO_OBJECT(v
),
3093 cx
->runtime
->atomState
.toSourceAtom
,
3094 0, NULL
, &tvr
.u
.value
)) {
3097 str
= js_ValueToString(cx
, tvr
.u
.value
);
3099 JS_POP_TEMP_ROOT(cx
, &tvr
);
3104 * str is not necessarily a GC thing here.
3107 js_HashString(JSString
*str
)
3113 JSSTRING_CHARS_AND_LENGTH(str
, s
, n
);
3114 for (h
= 0; n
; s
++, n
--)
3115 h
= JS_ROTATE_LEFT32(h
, 4) ^ *s
;
3120 * str is not necessarily a GC thing here.
3123 js_EqualStrings(JSString
*str1
, JSString
*str2
)
3126 const jschar
*s1
, *s2
;
3131 /* Fast case: pointer equality could be a quick win. */
3135 n
= JSSTRING_LENGTH(str1
);
3136 if (n
!= JSSTRING_LENGTH(str2
))
3142 s1
= JSSTRING_CHARS(str1
), s2
= JSSTRING_CHARS(str2
);
3153 js_CompareStrings(JSString
*str1
, JSString
*str2
)
3155 size_t l1
, l2
, n
, i
;
3156 const jschar
*s1
, *s2
;
3162 /* Fast case: pointer equality could be a quick win. */
3166 JSSTRING_CHARS_AND_LENGTH(str1
, s1
, l1
);
3167 JSSTRING_CHARS_AND_LENGTH(str2
, s2
, l2
);
3169 for (i
= 0; i
< n
; i
++) {
3170 cmp
= s1
[i
] - s2
[i
];
3174 return (intN
)(l1
- l2
);
3178 js_strlen(const jschar
*s
)
3182 for (t
= s
; *t
!= 0; t
++)
3184 return (size_t)(t
- s
);
3188 js_strchr(const jschar
*s
, jschar c
)
3199 js_strchr_limit(const jschar
*s
, jschar c
, const jschar
*limit
)
3210 js_SkipWhiteSpace(const jschar
*s
, const jschar
*end
)
3212 JS_ASSERT(s
<= end
);
3213 while (s
!= end
&& JS_ISSPACE(*s
))
3219 js_InflateString(JSContext
*cx
, const char *bytes
, size_t *lengthp
)
3221 size_t nbytes
, nchars
, i
;
3228 if (js_CStringsAreUTF8
) {
3229 if (!js_InflateStringToBuffer(cx
, bytes
, nbytes
, NULL
, &nchars
))
3231 chars
= (jschar
*) JS_malloc(cx
, (nchars
+ 1) * sizeof (jschar
));
3237 js_InflateStringToBuffer(cx
, bytes
, nbytes
, chars
, &nchars
);
3241 chars
= (jschar
*) JS_malloc(cx
, (nchars
+ 1) * sizeof(jschar
));
3244 for (i
= 0; i
< nchars
; i
++)
3245 chars
[i
] = (unsigned char) bytes
[i
];
3253 * For compatibility with callers of JS_DecodeBytes we must zero lengthp
3261 * May be called with null cx by js_GetStringBytes, see below.
3264 js_DeflateString(JSContext
*cx
, const jschar
*chars
, size_t nchars
)
3272 if (js_CStringsAreUTF8
) {
3273 nbytes
= js_GetDeflatedStringLength(cx
, chars
, nchars
);
3274 if (nbytes
== (size_t) -1)
3276 bytes
= (char *) (cx
? JS_malloc(cx
, nbytes
+ 1) : malloc(nbytes
+ 1));
3282 js_DeflateStringToBuffer(cx
, chars
, nchars
, bytes
, &nbytes
);
3286 bytes
= (char *) (cx
? JS_malloc(cx
, nbytes
+ 1) : malloc(nbytes
+ 1));
3289 for (i
= 0; i
< nbytes
; i
++)
3290 bytes
[i
] = (char) chars
[i
];
3297 * May be called with null cx through js_GetStringBytes, see below.
3300 js_GetDeflatedStringLength(JSContext
*cx
, const jschar
*chars
, size_t nchars
)
3307 if (!js_CStringsAreUTF8
)
3311 for (end
= chars
+ nchars
; chars
!= end
; chars
++) {
3315 if (0xD800 <= c
&& c
<= 0xDFFF) {
3316 /* Surrogate pair. */
3318 if (c
>= 0xDC00 || chars
== end
)
3321 if (c2
< 0xDC00 || c2
> 0xDFFF)
3323 c
= ((c
- 0xD800) << 10) + (c2
- 0xDC00) + 0x10000;
3336 JS_snprintf(buffer
, 10, "0x%x", c
);
3337 JS_ReportErrorFlagsAndNumber(cx
, JSREPORT_ERROR
, js_GetErrorMessage
,
3338 NULL
, JSMSG_BAD_SURROGATE_CHAR
, buffer
);
3344 js_DeflateStringToBuffer(JSContext
*cx
, const jschar
*src
, size_t srclen
,
3345 char *dst
, size_t *dstlenp
)
3347 size_t dstlen
, i
, origDstlen
, utf8Len
;
3353 if (!js_CStringsAreUTF8
) {
3354 if (srclen
> dstlen
) {
3355 for (i
= 0; i
< dstlen
; i
++)
3356 dst
[i
] = (char) src
[i
];
3358 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
3359 JSMSG_BUFFER_TOO_SMALL
);
3363 for (i
= 0; i
< srclen
; i
++)
3364 dst
[i
] = (char) src
[i
];
3369 origDstlen
= dstlen
;
3373 if ((c
>= 0xDC00) && (c
<= 0xDFFF))
3375 if (c
< 0xD800 || c
> 0xDBFF) {
3381 if ((c2
< 0xDC00) || (c2
> 0xDFFF))
3385 v
= ((c
- 0xD800) << 10) + (c2
- 0xDC00) + 0x10000;
3388 /* no encoding necessary - performance hack */
3390 goto bufferTooSmall
;
3394 utf8Len
= js_OneUcs4ToUtf8Char(utf8buf
, v
);
3395 if (utf8Len
> dstlen
)
3396 goto bufferTooSmall
;
3397 for (i
= 0; i
< utf8Len
; i
++)
3398 *dst
++ = (char) utf8buf
[i
];
3402 *dstlenp
= (origDstlen
- dstlen
);
3406 *dstlenp
= (origDstlen
- dstlen
);
3407 /* Delegate error reporting to the measurement function. */
3409 js_GetDeflatedStringLength(cx
, src
- 1, srclen
+ 1);
3413 *dstlenp
= (origDstlen
- dstlen
);
3415 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
3416 JSMSG_BUFFER_TOO_SMALL
);
3422 js_InflateStringToBuffer(JSContext
*cx
, const char *src
, size_t srclen
,
3423 jschar
*dst
, size_t *dstlenp
)
3425 size_t dstlen
, i
, origDstlen
, offset
, j
, n
;
3428 if (!js_CStringsAreUTF8
) {
3431 if (srclen
> dstlen
) {
3432 for (i
= 0; i
< dstlen
; i
++)
3433 dst
[i
] = (unsigned char) src
[i
];
3435 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
3436 JSMSG_BUFFER_TOO_SMALL
);
3440 for (i
= 0; i
< srclen
; i
++)
3441 dst
[i
] = (unsigned char) src
[i
];
3447 dstlen
= dst
? *dstlenp
: (size_t) -1;
3448 origDstlen
= dstlen
;
3455 while (v
& (0x80 >> n
))
3458 goto bufferTooSmall
;
3459 if (n
== 1 || n
> 6)
3461 for (j
= 1; j
< n
; j
++) {
3462 if ((src
[j
] & 0xC0) != 0x80)
3465 v
= Utf8ToOneUcs4Char((uint8
*)src
, n
);
3468 if (v
> 0xFFFFF || dstlen
< 2) {
3469 *dstlenp
= (origDstlen
- dstlen
);
3472 JS_snprintf(buffer
, 10, "0x%x", v
+ 0x10000);
3473 JS_ReportErrorFlagsAndNumber(cx
,
3475 js_GetErrorMessage
, NULL
,
3476 JSMSG_UTF8_CHAR_TOO_LARGE
,
3482 goto bufferTooSmall
;
3484 *dst
++ = (jschar
)((v
>> 10) + 0xD800);
3485 v
= (jschar
)((v
& 0x3FF) + 0xDC00);
3491 goto bufferTooSmall
;
3493 *dst
++ = (jschar
) v
;
3499 *dstlenp
= (origDstlen
- dstlen
);
3503 *dstlenp
= (origDstlen
- dstlen
);
3506 JS_snprintf(buffer
, 10, "%d", offset
);
3507 JS_ReportErrorFlagsAndNumber(cx
, JSREPORT_ERROR
,
3508 js_GetErrorMessage
, NULL
,
3509 JSMSG_MALFORMED_UTF8_CHAR
,
3515 *dstlenp
= (origDstlen
- dstlen
);
3517 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
3518 JSMSG_BUFFER_TOO_SMALL
);
3524 js_SetStringBytes(JSContext
*cx
, JSString
*str
, char *bytes
, size_t length
)
3533 JS_ACQUIRE_LOCK(rt
->deflatedStringCacheLock
);
3535 cache
= rt
->deflatedStringCache
;
3536 hash
= js_hash_string_pointer(str
);
3537 hep
= JS_HashTableRawLookup(cache
, hash
, str
);
3538 JS_ASSERT(*hep
== NULL
);
3539 ok
= JS_HashTableRawAdd(cache
, hep
, hash
, str
, bytes
) != NULL
;
3542 rt
->deflatedStringCacheBytes
+= length
;
3545 JS_RELEASE_LOCK(rt
->deflatedStringCacheLock
);
3550 js_GetStringBytes(JSContext
*cx
, JSString
*str
)
3556 JSHashEntry
*he
, **hep
;
3561 /* JS_GetStringBytes calls us with null cx. */
3562 rt
= js_GetGCStringRuntime(str
);
3565 #ifdef JS_THREADSAFE
3566 if (!rt
->deflatedStringCacheLock
) {
3568 * Called from last GC (see js_DestroyContext), after runtime string
3569 * state has been finalized. We have no choice but to leak here.
3571 return js_DeflateString(NULL
, JSSTRING_CHARS(str
),
3572 JSSTRING_LENGTH(str
));
3576 JS_ACQUIRE_LOCK(rt
->deflatedStringCacheLock
);
3578 cache
= rt
->deflatedStringCache
;
3579 hash
= js_hash_string_pointer(str
);
3580 hep
= JS_HashTableRawLookup(cache
, hash
, str
);
3583 bytes
= (char *) he
->value
;
3585 /* Try to catch failure to JS_ShutDown between runtime epochs. */
3586 if (!js_CStringsAreUTF8
) {
3587 JS_ASSERT_IF(*bytes
!= (char) JSSTRING_CHARS(str
)[0],
3588 *bytes
== '\0' && JSSTRING_LENGTH(str
) == 0);
3591 bytes
= js_DeflateString(cx
, JSSTRING_CHARS(str
),
3592 JSSTRING_LENGTH(str
));
3594 if (JS_HashTableRawAdd(cache
, hep
, hash
, str
, bytes
)) {
3596 rt
->deflatedStringCacheBytes
+= JSSTRING_LENGTH(str
);
3608 JS_RELEASE_LOCK(rt
->deflatedStringCacheLock
);
3613 * From java.lang.Character.java:
3615 * The character properties are currently encoded into 32 bits in the
3618 * 10 bits signed offset used for converting case
3619 * 1 bit if 1, adding the signed offset converts the character to
3621 * 1 bit if 1, subtracting the signed offset converts the character to
3623 * 1 bit if 1, character has a titlecase equivalent (possibly itself)
3624 * 3 bits 0 may not be part of an identifier
3625 * 1 ignorable control; may continue a Unicode identifier or JS
3627 * 2 may continue a JS identifier but not a Unicode identifier
3629 * 3 may continue a Unicode identifier or JS identifier
3630 * 4 is a JS whitespace character
3631 * 5 may start or continue a JS identifier;
3632 * may continue but not start a Unicode identifier (_)
3633 * 6 may start or continue a JS identifier but not a Unicode
3635 * 7 may start or continue a Unicode identifier or JS identifier
3637 * 5, 6, 7 may start a JS identifier
3638 * 1, 2, 3, 5, 6, 7 may continue a JS identifier
3639 * 7 may start a Unicode identifier
3640 * 1, 3, 5, 7 may continue a Unicode identifier
3641 * 1 is ignorable within an identifier
3642 * 4 is JS whitespace
3643 * 2 bits 0 this character has no numeric property
3644 * 1 adding the digit offset to the character code and then
3645 * masking with 0x1F will produce the desired numeric value
3646 * 2 this character has a "strange" numeric value
3647 * 3 a JS supradecimal digit: adding the digit offset to the
3648 * character code, then masking with 0x1F, then adding 10
3649 * will produce the desired numeric value
3650 * 5 bits digit offset
3651 * 1 bit XML 1.0 name start character
3652 * 1 bit XML 1.0 name character
3653 * 2 bits reserved for future use
3654 * 5 bits character type
3657 /* The X table has 1024 entries for a total of 1024 bytes. */
3659 const uint8 js_X
[] = {
3660 0, 1, 2, 3, 4, 5, 6, 7, /* 0x0000 */
3661 8, 9, 10, 11, 12, 13, 14, 15, /* 0x0200 */
3662 16, 17, 18, 19, 20, 21, 22, 23, /* 0x0400 */
3663 24, 25, 26, 27, 28, 28, 28, 28, /* 0x0600 */
3664 28, 28, 28, 28, 29, 30, 31, 32, /* 0x0800 */
3665 33, 34, 35, 36, 37, 38, 39, 40, /* 0x0A00 */
3666 41, 42, 43, 44, 45, 46, 28, 28, /* 0x0C00 */
3667 47, 48, 49, 50, 51, 52, 53, 28, /* 0x0E00 */
3668 28, 28, 54, 55, 56, 57, 58, 59, /* 0x1000 */
3669 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1200 */
3670 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1400 */
3671 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1600 */
3672 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1800 */
3673 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1A00 */
3674 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1C00 */
3675 60, 60, 61, 62, 63, 64, 65, 66, /* 0x1E00 */
3676 67, 68, 69, 70, 71, 72, 73, 74, /* 0x2000 */
3677 75, 75, 75, 76, 77, 78, 28, 28, /* 0x2200 */
3678 79, 80, 81, 82, 83, 83, 84, 85, /* 0x2400 */
3679 86, 85, 28, 28, 87, 88, 89, 28, /* 0x2600 */
3680 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2800 */
3681 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2A00 */
3682 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2C00 */
3683 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2E00 */
3684 90, 91, 92, 93, 94, 56, 95, 28, /* 0x3000 */
3685 96, 97, 98, 99, 83, 100, 83, 101, /* 0x3200 */
3686 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3400 */
3687 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3600 */
3688 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3800 */
3689 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3A00 */
3690 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3C00 */
3691 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3E00 */
3692 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4000 */
3693 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4200 */
3694 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4400 */
3695 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4600 */
3696 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4800 */
3697 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4A00 */
3698 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4C00 */
3699 56, 56, 56, 56, 56, 56, 56, 56, /* 0x4E00 */
3700 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5000 */
3701 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5200 */
3702 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5400 */
3703 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5600 */
3704 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5800 */
3705 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5A00 */
3706 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5C00 */
3707 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5E00 */
3708 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6000 */
3709 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6200 */
3710 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6400 */
3711 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6600 */
3712 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6800 */
3713 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6A00 */
3714 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6C00 */
3715 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6E00 */
3716 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7000 */
3717 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7200 */
3718 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7400 */
3719 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7600 */
3720 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7800 */
3721 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7A00 */
3722 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7C00 */
3723 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7E00 */
3724 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8000 */
3725 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8200 */
3726 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8400 */
3727 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8600 */
3728 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8800 */
3729 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8A00 */
3730 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8C00 */
3731 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8E00 */
3732 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9000 */
3733 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9200 */
3734 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9400 */
3735 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9600 */
3736 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9800 */
3737 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9A00 */
3738 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9C00 */
3739 56, 56, 56, 56, 56, 56, 102, 28, /* 0x9E00 */
3740 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA000 */
3741 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA200 */
3742 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA400 */
3743 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA600 */
3744 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA800 */
3745 28, 28, 28, 28, 28, 28, 28, 28, /* 0xAA00 */
3746 56, 56, 56, 56, 56, 56, 56, 56, /* 0xAC00 */
3747 56, 56, 56, 56, 56, 56, 56, 56, /* 0xAE00 */
3748 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB000 */
3749 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB200 */
3750 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB400 */
3751 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB600 */
3752 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB800 */
3753 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBA00 */
3754 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBC00 */
3755 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBE00 */
3756 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC000 */
3757 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC200 */
3758 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC400 */
3759 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC600 */
3760 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC800 */
3761 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCA00 */
3762 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCC00 */
3763 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCE00 */
3764 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD000 */
3765 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD200 */
3766 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD400 */
3767 56, 56, 56, 56, 56, 56, 103, 28, /* 0xD600 */
3768 104, 104, 104, 104, 104, 104, 104, 104, /* 0xD800 */
3769 104, 104, 104, 104, 104, 104, 104, 104, /* 0xDA00 */
3770 104, 104, 104, 104, 104, 104, 104, 104, /* 0xDC00 */
3771 104, 104, 104, 104, 104, 104, 104, 104, /* 0xDE00 */
3772 105, 105, 105, 105, 105, 105, 105, 105, /* 0xE000 */
3773 105, 105, 105, 105, 105, 105, 105, 105, /* 0xE200 */
3774 105, 105, 105, 105, 105, 105, 105, 105, /* 0xE400 */
3775 105, 105, 105, 105, 105, 105, 105, 105, /* 0xE600 */
3776 105, 105, 105, 105, 105, 105, 105, 105, /* 0xE800 */
3777 105, 105, 105, 105, 105, 105, 105, 105, /* 0xEA00 */
3778 105, 105, 105, 105, 105, 105, 105, 105, /* 0xEC00 */
3779 105, 105, 105, 105, 105, 105, 105, 105, /* 0xEE00 */
3780 105, 105, 105, 105, 105, 105, 105, 105, /* 0xF000 */
3781 105, 105, 105, 105, 105, 105, 105, 105, /* 0xF200 */
3782 105, 105, 105, 105, 105, 105, 105, 105, /* 0xF400 */
3783 105, 105, 105, 105, 105, 105, 105, 105, /* 0xF600 */
3784 105, 105, 105, 105, 56, 56, 56, 56, /* 0xF800 */
3785 106, 28, 28, 28, 107, 108, 109, 110, /* 0xFA00 */
3786 56, 56, 56, 56, 111, 112, 113, 114, /* 0xFC00 */
3787 115, 116, 56, 117, 118, 119, 120, 121 /* 0xFE00 */
3790 /* The Y table has 7808 entries for a total of 7808 bytes. */
3792 const uint8 js_Y
[] = {
3793 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
3794 0, 1, 1, 1, 1, 1, 0, 0, /* 0 */
3795 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
3796 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
3797 2, 3, 3, 3, 4, 3, 3, 3, /* 0 */
3798 5, 6, 3, 7, 3, 8, 3, 3, /* 0 */
3799 9, 9, 9, 9, 9, 9, 9, 9, /* 0 */
3800 9, 9, 3, 3, 7, 7, 7, 3, /* 0 */
3801 3, 10, 10, 10, 10, 10, 10, 10, /* 1 */
3802 10, 10, 10, 10, 10, 10, 10, 10, /* 1 */
3803 10, 10, 10, 10, 10, 10, 10, 10, /* 1 */
3804 10, 10, 10, 5, 3, 6, 11, 12, /* 1 */
3805 11, 13, 13, 13, 13, 13, 13, 13, /* 1 */
3806 13, 13, 13, 13, 13, 13, 13, 13, /* 1 */
3807 13, 13, 13, 13, 13, 13, 13, 13, /* 1 */
3808 13, 13, 13, 5, 7, 6, 7, 0, /* 1 */
3809 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
3810 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
3811 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
3812 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
3813 2, 3, 4, 4, 4, 4, 15, 15, /* 2 */
3814 11, 15, 16, 5, 7, 8, 15, 11, /* 2 */
3815 15, 7, 17, 17, 11, 16, 15, 3, /* 2 */
3816 11, 18, 16, 6, 19, 19, 19, 3, /* 2 */
3817 20, 20, 20, 20, 20, 20, 20, 20, /* 3 */
3818 20, 20, 20, 20, 20, 20, 20, 20, /* 3 */
3819 20, 20, 20, 20, 20, 20, 20, 7, /* 3 */
3820 20, 20, 20, 20, 20, 20, 20, 16, /* 3 */
3821 21, 21, 21, 21, 21, 21, 21, 21, /* 3 */
3822 21, 21, 21, 21, 21, 21, 21, 21, /* 3 */
3823 21, 21, 21, 21, 21, 21, 21, 7, /* 3 */
3824 21, 21, 21, 21, 21, 21, 21, 22, /* 3 */
3825 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
3826 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
3827 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
3828 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
3829 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
3830 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
3831 25, 26, 23, 24, 23, 24, 23, 24, /* 4 */
3832 16, 23, 24, 23, 24, 23, 24, 23, /* 4 */
3833 24, 23, 24, 23, 24, 23, 24, 23, /* 5 */
3834 24, 16, 23, 24, 23, 24, 23, 24, /* 5 */
3835 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
3836 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
3837 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
3838 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
3839 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
3840 27, 23, 24, 23, 24, 23, 24, 28, /* 5 */
3841 16, 29, 23, 24, 23, 24, 30, 23, /* 6 */
3842 24, 31, 31, 23, 24, 16, 32, 32, /* 6 */
3843 33, 23, 24, 31, 34, 16, 35, 36, /* 6 */
3844 23, 24, 16, 16, 35, 37, 16, 38, /* 6 */
3845 23, 24, 23, 24, 23, 24, 38, 23, /* 6 */
3846 24, 39, 40, 16, 23, 24, 39, 23, /* 6 */
3847 24, 41, 41, 23, 24, 23, 24, 42, /* 6 */
3848 23, 24, 16, 40, 23, 24, 40, 40, /* 6 */
3849 40, 40, 40, 40, 43, 44, 45, 43, /* 7 */
3850 44, 45, 43, 44, 45, 23, 24, 23, /* 7 */
3851 24, 23, 24, 23, 24, 23, 24, 23, /* 7 */
3852 24, 23, 24, 23, 24, 16, 23, 24, /* 7 */
3853 23, 24, 23, 24, 23, 24, 23, 24, /* 7 */
3854 23, 24, 23, 24, 23, 24, 23, 24, /* 7 */
3855 16, 43, 44, 45, 23, 24, 46, 46, /* 7 */
3856 46, 46, 23, 24, 23, 24, 23, 24, /* 7 */
3857 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */
3858 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */
3859 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */
3860 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
3861 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
3862 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
3863 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
3864 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
3865 46, 46, 46, 46, 46, 46, 46, 46, /* 9 */
3866 46, 46, 46, 46, 46, 46, 46, 46, /* 9 */
3867 16, 16, 16, 47, 48, 16, 49, 49, /* 9 */
3868 50, 50, 16, 51, 16, 16, 16, 16, /* 9 */
3869 49, 16, 16, 52, 16, 16, 16, 16, /* 9 */
3870 53, 54, 16, 16, 16, 16, 16, 54, /* 9 */
3871 16, 16, 55, 16, 16, 16, 16, 16, /* 9 */
3872 16, 16, 16, 16, 16, 16, 16, 16, /* 9 */
3873 16, 16, 16, 56, 16, 16, 16, 16, /* 10 */
3874 56, 16, 57, 57, 16, 16, 16, 16, /* 10 */
3875 16, 16, 58, 16, 16, 16, 16, 16, /* 10 */
3876 16, 16, 16, 16, 16, 16, 16, 16, /* 10 */
3877 16, 16, 16, 16, 16, 16, 16, 16, /* 10 */
3878 16, 46, 46, 46, 46, 46, 46, 46, /* 10 */
3879 59, 59, 59, 59, 59, 59, 59, 59, /* 10 */
3880 59, 11, 11, 59, 59, 59, 59, 59, /* 10 */
3881 59, 59, 11, 11, 11, 11, 11, 11, /* 11 */
3882 11, 11, 11, 11, 11, 11, 11, 11, /* 11 */
3883 59, 59, 11, 11, 11, 11, 11, 11, /* 11 */
3884 11, 11, 11, 11, 11, 11, 11, 46, /* 11 */
3885 59, 59, 59, 59, 59, 11, 11, 11, /* 11 */
3886 11, 11, 46, 46, 46, 46, 46, 46, /* 11 */
3887 46, 46, 46, 46, 46, 46, 46, 46, /* 11 */
3888 46, 46, 46, 46, 46, 46, 46, 46, /* 11 */
3889 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
3890 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
3891 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
3892 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
3893 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
3894 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
3895 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
3896 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
3897 60, 60, 60, 60, 60, 60, 46, 46, /* 13 */
3898 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
3899 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
3900 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
3901 60, 60, 46, 46, 46, 46, 46, 46, /* 13 */
3902 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
3903 46, 46, 46, 46, 3, 3, 46, 46, /* 13 */
3904 46, 46, 59, 46, 46, 46, 3, 46, /* 13 */
3905 46, 46, 46, 46, 11, 11, 61, 3, /* 14 */
3906 62, 62, 62, 46, 63, 46, 64, 64, /* 14 */
3907 16, 20, 20, 20, 20, 20, 20, 20, /* 14 */
3908 20, 20, 20, 20, 20, 20, 20, 20, /* 14 */
3909 20, 20, 46, 20, 20, 20, 20, 20, /* 14 */
3910 20, 20, 20, 20, 65, 66, 66, 66, /* 14 */
3911 16, 21, 21, 21, 21, 21, 21, 21, /* 14 */
3912 21, 21, 21, 21, 21, 21, 21, 21, /* 14 */
3913 21, 21, 16, 21, 21, 21, 21, 21, /* 15 */
3914 21, 21, 21, 21, 67, 68, 68, 46, /* 15 */
3915 69, 70, 38, 38, 38, 71, 72, 46, /* 15 */
3916 46, 46, 38, 46, 38, 46, 38, 46, /* 15 */
3917 38, 46, 23, 24, 23, 24, 23, 24, /* 15 */
3918 23, 24, 23, 24, 23, 24, 23, 24, /* 15 */
3919 73, 74, 16, 40, 46, 46, 46, 46, /* 15 */
3920 46, 46, 46, 46, 46, 46, 46, 46, /* 15 */
3921 46, 75, 75, 75, 75, 75, 75, 75, /* 16 */
3922 75, 75, 75, 75, 75, 46, 75, 75, /* 16 */
3923 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
3924 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
3925 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
3926 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
3927 21, 21, 21, 21, 21, 21, 21, 21, /* 16 */
3928 21, 21, 21, 21, 21, 21, 21, 21, /* 16 */
3929 21, 21, 21, 21, 21, 21, 21, 21, /* 17 */
3930 21, 21, 21, 21, 21, 21, 21, 21, /* 17 */
3931 46, 74, 74, 74, 74, 74, 74, 74, /* 17 */
3932 74, 74, 74, 74, 74, 46, 74, 74, /* 17 */
3933 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
3934 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
3935 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
3936 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
3937 23, 24, 15, 60, 60, 60, 60, 46, /* 18 */
3938 46, 46, 46, 46, 46, 46, 46, 46, /* 18 */
3939 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
3940 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
3941 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
3942 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
3943 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
3944 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
3945 40, 23, 24, 23, 24, 46, 46, 23, /* 19 */
3946 24, 46, 46, 23, 24, 46, 46, 46, /* 19 */
3947 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */
3948 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */
3949 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */
3950 23, 24, 23, 24, 46, 46, 23, 24, /* 19 */
3951 23, 24, 23, 24, 23, 24, 46, 46, /* 19 */
3952 23, 24, 46, 46, 46, 46, 46, 46, /* 19 */
3953 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
3954 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
3955 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
3956 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
3957 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
3958 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
3959 46, 76, 76, 76, 76, 76, 76, 76, /* 20 */
3960 76, 76, 76, 76, 76, 76, 76, 76, /* 20 */
3961 76, 76, 76, 76, 76, 76, 76, 76, /* 21 */
3962 76, 76, 76, 76, 76, 76, 76, 76, /* 21 */
3963 76, 76, 76, 76, 76, 76, 76, 46, /* 21 */
3964 46, 59, 3, 3, 3, 3, 3, 3, /* 21 */
3965 46, 77, 77, 77, 77, 77, 77, 77, /* 21 */
3966 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */
3967 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */
3968 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */
3969 77, 77, 77, 77, 77, 77, 77, 16, /* 22 */
3970 46, 3, 46, 46, 46, 46, 46, 46, /* 22 */
3971 46, 60, 60, 60, 60, 60, 60, 60, /* 22 */
3972 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */
3973 60, 60, 46, 60, 60, 60, 60, 60, /* 22 */
3974 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */
3975 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */
3976 60, 60, 46, 60, 60, 60, 3, 60, /* 22 */
3977 3, 60, 60, 3, 60, 46, 46, 46, /* 23 */
3978 46, 46, 46, 46, 46, 46, 46, 46, /* 23 */
3979 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */
3980 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */
3981 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */
3982 40, 40, 40, 46, 46, 46, 46, 46, /* 23 */
3983 40, 40, 40, 3, 3, 46, 46, 46, /* 23 */
3984 46, 46, 46, 46, 46, 46, 46, 46, /* 23 */
3985 46, 46, 46, 46, 46, 46, 46, 46, /* 24 */
3986 46, 46, 46, 46, 3, 46, 46, 46, /* 24 */
3987 46, 46, 46, 46, 46, 46, 46, 46, /* 24 */
3988 46, 46, 46, 3, 46, 46, 46, 3, /* 24 */
3989 46, 40, 40, 40, 40, 40, 40, 40, /* 24 */
3990 40, 40, 40, 40, 40, 40, 40, 40, /* 24 */
3991 40, 40, 40, 40, 40, 40, 40, 40, /* 24 */
3992 40, 40, 40, 46, 46, 46, 46, 46, /* 24 */
3993 59, 40, 40, 40, 40, 40, 40, 40, /* 25 */
3994 40, 40, 40, 60, 60, 60, 60, 60, /* 25 */
3995 60, 60, 60, 46, 46, 46, 46, 46, /* 25 */
3996 46, 46, 46, 46, 46, 46, 46, 46, /* 25 */
3997 78, 78, 78, 78, 78, 78, 78, 78, /* 25 */
3998 78, 78, 3, 3, 3, 3, 46, 46, /* 25 */
3999 60, 40, 40, 40, 40, 40, 40, 40, /* 25 */
4000 40, 40, 40, 40, 40, 40, 40, 40, /* 25 */
4001 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
4002 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
4003 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
4004 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
4005 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
4006 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
4007 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
4008 46, 46, 40, 40, 40, 40, 40, 46, /* 26 */
4009 40, 40, 40, 40, 40, 40, 40, 40, /* 27 */
4010 40, 40, 40, 40, 40, 40, 40, 46, /* 27 */
4011 40, 40, 40, 40, 3, 40, 60, 60, /* 27 */
4012 60, 60, 60, 60, 60, 79, 79, 60, /* 27 */
4013 60, 60, 60, 60, 60, 59, 59, 60, /* 27 */
4014 60, 15, 60, 60, 60, 60, 46, 46, /* 27 */
4015 9, 9, 9, 9, 9, 9, 9, 9, /* 27 */
4016 9, 9, 46, 46, 46, 46, 46, 46, /* 27 */
4017 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
4018 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
4019 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
4020 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
4021 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
4022 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
4023 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
4024 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
4025 46, 60, 60, 80, 46, 40, 40, 40, /* 29 */
4026 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
4027 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
4028 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
4029 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
4030 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
4031 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
4032 40, 40, 46, 46, 60, 40, 80, 80, /* 29 */
4033 80, 60, 60, 60, 60, 60, 60, 60, /* 30 */
4034 60, 80, 80, 80, 80, 60, 46, 46, /* 30 */
4035 15, 60, 60, 60, 60, 46, 46, 46, /* 30 */
4036 40, 40, 40, 40, 40, 40, 40, 40, /* 30 */
4037 40, 40, 60, 60, 3, 3, 81, 81, /* 30 */
4038 81, 81, 81, 81, 81, 81, 81, 81, /* 30 */
4039 3, 46, 46, 46, 46, 46, 46, 46, /* 30 */
4040 46, 46, 46, 46, 46, 46, 46, 46, /* 30 */
4041 46, 60, 80, 80, 46, 40, 40, 40, /* 31 */
4042 40, 40, 40, 40, 40, 46, 46, 40, /* 31 */
4043 40, 46, 46, 40, 40, 40, 40, 40, /* 31 */
4044 40, 40, 40, 40, 40, 40, 40, 40, /* 31 */
4045 40, 40, 40, 40, 40, 40, 40, 40, /* 31 */
4046 40, 46, 40, 40, 40, 40, 40, 40, /* 31 */
4047 40, 46, 40, 46, 46, 46, 40, 40, /* 31 */
4048 40, 40, 46, 46, 60, 46, 80, 80, /* 31 */
4049 80, 60, 60, 60, 60, 46, 46, 80, /* 32 */
4050 80, 46, 46, 80, 80, 60, 46, 46, /* 32 */
4051 46, 46, 46, 46, 46, 46, 46, 80, /* 32 */
4052 46, 46, 46, 46, 40, 40, 46, 40, /* 32 */
4053 40, 40, 60, 60, 46, 46, 81, 81, /* 32 */
4054 81, 81, 81, 81, 81, 81, 81, 81, /* 32 */
4055 40, 40, 4, 4, 82, 82, 82, 82, /* 32 */
4056 19, 83, 15, 46, 46, 46, 46, 46, /* 32 */
4057 46, 46, 60, 46, 46, 40, 40, 40, /* 33 */
4058 40, 40, 40, 46, 46, 46, 46, 40, /* 33 */
4059 40, 46, 46, 40, 40, 40, 40, 40, /* 33 */
4060 40, 40, 40, 40, 40, 40, 40, 40, /* 33 */
4061 40, 40, 40, 40, 40, 40, 40, 40, /* 33 */
4062 40, 46, 40, 40, 40, 40, 40, 40, /* 33 */
4063 40, 46, 40, 40, 46, 40, 40, 46, /* 33 */
4064 40, 40, 46, 46, 60, 46, 80, 80, /* 33 */
4065 80, 60, 60, 46, 46, 46, 46, 60, /* 34 */
4066 60, 46, 46, 60, 60, 60, 46, 46, /* 34 */
4067 46, 46, 46, 46, 46, 46, 46, 46, /* 34 */
4068 46, 40, 40, 40, 40, 46, 40, 46, /* 34 */
4069 46, 46, 46, 46, 46, 46, 81, 81, /* 34 */
4070 81, 81, 81, 81, 81, 81, 81, 81, /* 34 */
4071 60, 60, 40, 40, 40, 46, 46, 46, /* 34 */
4072 46, 46, 46, 46, 46, 46, 46, 46, /* 34 */
4073 46, 60, 60, 80, 46, 40, 40, 40, /* 35 */
4074 40, 40, 40, 40, 46, 40, 46, 40, /* 35 */
4075 40, 40, 46, 40, 40, 40, 40, 40, /* 35 */
4076 40, 40, 40, 40, 40, 40, 40, 40, /* 35 */
4077 40, 40, 40, 40, 40, 40, 40, 40, /* 35 */
4078 40, 46, 40, 40, 40, 40, 40, 40, /* 35 */
4079 40, 46, 40, 40, 46, 40, 40, 40, /* 35 */
4080 40, 40, 46, 46, 60, 40, 80, 80, /* 35 */
4081 80, 60, 60, 60, 60, 60, 46, 60, /* 36 */
4082 60, 80, 46, 80, 80, 60, 46, 46, /* 36 */
4083 15, 46, 46, 46, 46, 46, 46, 46, /* 36 */
4084 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */
4085 40, 46, 46, 46, 46, 46, 81, 81, /* 36 */
4086 81, 81, 81, 81, 81, 81, 81, 81, /* 36 */
4087 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */
4088 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */
4089 46, 60, 80, 80, 46, 40, 40, 40, /* 37 */
4090 40, 40, 40, 40, 40, 46, 46, 40, /* 37 */
4091 40, 46, 46, 40, 40, 40, 40, 40, /* 37 */
4092 40, 40, 40, 40, 40, 40, 40, 40, /* 37 */
4093 40, 40, 40, 40, 40, 40, 40, 40, /* 37 */
4094 40, 46, 40, 40, 40, 40, 40, 40, /* 37 */
4095 40, 46, 40, 40, 46, 46, 40, 40, /* 37 */
4096 40, 40, 46, 46, 60, 40, 80, 60, /* 37 */
4097 80, 60, 60, 60, 46, 46, 46, 80, /* 38 */
4098 80, 46, 46, 80, 80, 60, 46, 46, /* 38 */
4099 46, 46, 46, 46, 46, 46, 60, 80, /* 38 */
4100 46, 46, 46, 46, 40, 40, 46, 40, /* 38 */
4101 40, 40, 46, 46, 46, 46, 81, 81, /* 38 */
4102 81, 81, 81, 81, 81, 81, 81, 81, /* 38 */
4103 15, 46, 46, 46, 46, 46, 46, 46, /* 38 */
4104 46, 46, 46, 46, 46, 46, 46, 46, /* 38 */
4105 46, 46, 60, 80, 46, 40, 40, 40, /* 39 */
4106 40, 40, 40, 46, 46, 46, 40, 40, /* 39 */
4107 40, 46, 40, 40, 40, 40, 46, 46, /* 39 */
4108 46, 40, 40, 46, 40, 46, 40, 40, /* 39 */
4109 46, 46, 46, 40, 40, 46, 46, 46, /* 39 */
4110 40, 40, 40, 46, 46, 46, 40, 40, /* 39 */
4111 40, 40, 40, 40, 40, 40, 46, 40, /* 39 */
4112 40, 40, 46, 46, 46, 46, 80, 80, /* 39 */
4113 60, 80, 80, 46, 46, 46, 80, 80, /* 40 */
4114 80, 46, 80, 80, 80, 60, 46, 46, /* 40 */
4115 46, 46, 46, 46, 46, 46, 46, 80, /* 40 */
4116 46, 46, 46, 46, 46, 46, 46, 46, /* 40 */
4117 46, 46, 46, 46, 46, 46, 46, 81, /* 40 */
4118 81, 81, 81, 81, 81, 81, 81, 81, /* 40 */
4119 84, 19, 19, 46, 46, 46, 46, 46, /* 40 */
4120 46, 46, 46, 46, 46, 46, 46, 46, /* 40 */
4121 46, 80, 80, 80, 46, 40, 40, 40, /* 41 */
4122 40, 40, 40, 40, 40, 46, 40, 40, /* 41 */
4123 40, 46, 40, 40, 40, 40, 40, 40, /* 41 */
4124 40, 40, 40, 40, 40, 40, 40, 40, /* 41 */
4125 40, 40, 40, 40, 40, 40, 40, 40, /* 41 */
4126 40, 46, 40, 40, 40, 40, 40, 40, /* 41 */
4127 40, 40, 40, 40, 46, 40, 40, 40, /* 41 */
4128 40, 40, 46, 46, 46, 46, 60, 60, /* 41 */
4129 60, 80, 80, 80, 80, 46, 60, 60, /* 42 */
4130 60, 46, 60, 60, 60, 60, 46, 46, /* 42 */
4131 46, 46, 46, 46, 46, 60, 60, 46, /* 42 */
4132 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */
4133 40, 40, 46, 46, 46, 46, 81, 81, /* 42 */
4134 81, 81, 81, 81, 81, 81, 81, 81, /* 42 */
4135 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */
4136 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */
4137 46, 46, 80, 80, 46, 40, 40, 40, /* 43 */
4138 40, 40, 40, 40, 40, 46, 40, 40, /* 43 */
4139 40, 46, 40, 40, 40, 40, 40, 40, /* 43 */
4140 40, 40, 40, 40, 40, 40, 40, 40, /* 43 */
4141 40, 40, 40, 40, 40, 40, 40, 40, /* 43 */
4142 40, 46, 40, 40, 40, 40, 40, 40, /* 43 */
4143 40, 40, 40, 40, 46, 40, 40, 40, /* 43 */
4144 40, 40, 46, 46, 46, 46, 80, 60, /* 43 */
4145 80, 80, 80, 80, 80, 46, 60, 80, /* 44 */
4146 80, 46, 80, 80, 60, 60, 46, 46, /* 44 */
4147 46, 46, 46, 46, 46, 80, 80, 46, /* 44 */
4148 46, 46, 46, 46, 46, 46, 40, 46, /* 44 */
4149 40, 40, 46, 46, 46, 46, 81, 81, /* 44 */
4150 81, 81, 81, 81, 81, 81, 81, 81, /* 44 */
4151 46, 46, 46, 46, 46, 46, 46, 46, /* 44 */
4152 46, 46, 46, 46, 46, 46, 46, 46, /* 44 */
4153 46, 46, 80, 80, 46, 40, 40, 40, /* 45 */
4154 40, 40, 40, 40, 40, 46, 40, 40, /* 45 */
4155 40, 46, 40, 40, 40, 40, 40, 40, /* 45 */
4156 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */
4157 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */
4158 40, 46, 40, 40, 40, 40, 40, 40, /* 45 */
4159 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */
4160 40, 40, 46, 46, 46, 46, 80, 80, /* 45 */
4161 80, 60, 60, 60, 46, 46, 80, 80, /* 46 */
4162 80, 46, 80, 80, 80, 60, 46, 46, /* 46 */
4163 46, 46, 46, 46, 46, 46, 46, 80, /* 46 */
4164 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */
4165 40, 40, 46, 46, 46, 46, 81, 81, /* 46 */
4166 81, 81, 81, 81, 81, 81, 81, 81, /* 46 */
4167 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */
4168 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */
4169 46, 40, 40, 40, 40, 40, 40, 40, /* 47 */
4170 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
4171 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
4172 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
4173 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
4174 40, 40, 40, 40, 40, 40, 40, 3, /* 47 */
4175 40, 60, 40, 40, 60, 60, 60, 60, /* 47 */
4176 60, 60, 60, 46, 46, 46, 46, 4, /* 47 */
4177 40, 40, 40, 40, 40, 40, 59, 60, /* 48 */
4178 60, 60, 60, 60, 60, 60, 60, 15, /* 48 */
4179 9, 9, 9, 9, 9, 9, 9, 9, /* 48 */
4180 9, 9, 3, 3, 46, 46, 46, 46, /* 48 */
4181 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
4182 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
4183 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
4184 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
4185 46, 40, 40, 46, 40, 46, 46, 40, /* 49 */
4186 40, 46, 40, 46, 46, 40, 46, 46, /* 49 */
4187 46, 46, 46, 46, 40, 40, 40, 40, /* 49 */
4188 46, 40, 40, 40, 40, 40, 40, 40, /* 49 */
4189 46, 40, 40, 40, 46, 40, 46, 40, /* 49 */
4190 46, 46, 40, 40, 46, 40, 40, 3, /* 49 */
4191 40, 60, 40, 40, 60, 60, 60, 60, /* 49 */
4192 60, 60, 46, 60, 60, 40, 46, 46, /* 49 */
4193 40, 40, 40, 40, 40, 46, 59, 46, /* 50 */
4194 60, 60, 60, 60, 60, 60, 46, 46, /* 50 */
4195 9, 9, 9, 9, 9, 9, 9, 9, /* 50 */
4196 9, 9, 46, 46, 40, 40, 46, 46, /* 50 */
4197 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
4198 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
4199 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
4200 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
4201 15, 15, 15, 15, 3, 3, 3, 3, /* 51 */
4202 3, 3, 3, 3, 3, 3, 3, 3, /* 51 */
4203 3, 3, 3, 15, 15, 15, 15, 15, /* 51 */
4204 60, 60, 15, 15, 15, 15, 15, 15, /* 51 */
4205 78, 78, 78, 78, 78, 78, 78, 78, /* 51 */
4206 78, 78, 85, 85, 85, 85, 85, 85, /* 51 */
4207 85, 85, 85, 85, 15, 60, 15, 60, /* 51 */
4208 15, 60, 5, 6, 5, 6, 80, 80, /* 51 */
4209 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
4210 46, 40, 40, 40, 40, 40, 40, 40, /* 52 */
4211 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
4212 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
4213 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
4214 40, 40, 46, 46, 46, 46, 46, 46, /* 52 */
4215 46, 60, 60, 60, 60, 60, 60, 60, /* 52 */
4216 60, 60, 60, 60, 60, 60, 60, 80, /* 52 */
4217 60, 60, 60, 60, 60, 3, 60, 60, /* 53 */
4218 60, 60, 60, 60, 46, 46, 46, 46, /* 53 */
4219 60, 60, 60, 60, 60, 60, 46, 60, /* 53 */
4220 46, 60, 60, 60, 60, 60, 60, 60, /* 53 */
4221 60, 60, 60, 60, 60, 60, 60, 60, /* 53 */
4222 60, 60, 60, 60, 60, 60, 46, 46, /* 53 */
4223 46, 60, 60, 60, 60, 60, 60, 60, /* 53 */
4224 46, 60, 46, 46, 46, 46, 46, 46, /* 53 */
4225 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
4226 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
4227 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
4228 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
4229 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
4230 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
4231 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
4232 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
4233 76, 76, 76, 76, 76, 76, 46, 46, /* 55 */
4234 46, 46, 46, 46, 46, 46, 46, 46, /* 55 */
4235 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
4236 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
4237 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
4238 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
4239 16, 16, 16, 16, 16, 16, 16, 46, /* 55 */
4240 46, 46, 46, 3, 46, 46, 46, 46, /* 55 */
4241 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
4242 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
4243 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
4244 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
4245 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
4246 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
4247 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
4248 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
4249 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
4250 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
4251 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
4252 40, 40, 46, 46, 46, 46, 46, 40, /* 57 */
4253 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
4254 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
4255 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
4256 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
4257 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
4258 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
4259 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
4260 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
4261 40, 40, 40, 46, 46, 46, 46, 46, /* 58 */
4262 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
4263 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
4264 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
4265 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
4266 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
4267 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
4268 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
4269 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
4270 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
4271 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
4272 40, 40, 46, 46, 46, 46, 46, 46, /* 59 */
4273 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
4274 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
4275 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
4276 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
4277 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
4278 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
4279 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
4280 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
4281 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
4282 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
4283 23, 24, 23, 24, 23, 24, 16, 16, /* 61 */
4284 16, 16, 16, 16, 46, 46, 46, 46, /* 61 */
4285 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
4286 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
4287 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
4288 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
4289 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
4290 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
4291 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
4292 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
4293 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
4294 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
4295 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
4296 23, 24, 46, 46, 46, 46, 46, 46, /* 62 */
4297 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */
4298 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */
4299 86, 86, 86, 86, 86, 86, 46, 46, /* 63 */
4300 87, 87, 87, 87, 87, 87, 46, 46, /* 63 */
4301 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */
4302 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */
4303 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */
4304 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */
4305 86, 86, 86, 86, 86, 86, 46, 46, /* 64 */
4306 87, 87, 87, 87, 87, 87, 46, 46, /* 64 */
4307 16, 86, 16, 86, 16, 86, 16, 86, /* 64 */
4308 46, 87, 46, 87, 46, 87, 46, 87, /* 64 */
4309 86, 86, 86, 86, 86, 86, 86, 86, /* 64 */
4310 87, 87, 87, 87, 87, 87, 87, 87, /* 64 */
4311 88, 88, 89, 89, 89, 89, 90, 90, /* 64 */
4312 91, 91, 92, 92, 93, 93, 46, 46, /* 64 */
4313 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */
4314 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */
4315 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */
4316 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */
4317 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */
4318 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */
4319 86, 86, 16, 94, 16, 46, 16, 16, /* 65 */
4320 87, 87, 95, 95, 96, 11, 38, 11, /* 65 */
4321 11, 11, 16, 94, 16, 46, 16, 16, /* 66 */
4322 97, 97, 97, 97, 96, 11, 11, 11, /* 66 */
4323 86, 86, 16, 16, 46, 46, 16, 16, /* 66 */
4324 87, 87, 98, 98, 46, 11, 11, 11, /* 66 */
4325 86, 86, 16, 16, 16, 99, 16, 16, /* 66 */
4326 87, 87, 100, 100, 101, 11, 11, 11, /* 66 */
4327 46, 46, 16, 94, 16, 46, 16, 16, /* 66 */
4328 102, 102, 103, 103, 96, 11, 11, 46, /* 66 */
4329 2, 2, 2, 2, 2, 2, 2, 2, /* 67 */
4330 2, 2, 2, 2, 104, 104, 104, 104, /* 67 */
4331 8, 8, 8, 8, 8, 8, 3, 3, /* 67 */
4332 5, 6, 5, 5, 5, 6, 5, 5, /* 67 */
4333 3, 3, 3, 3, 3, 3, 3, 3, /* 67 */
4334 105, 106, 104, 104, 104, 104, 104, 46, /* 67 */
4335 3, 3, 3, 3, 3, 3, 3, 3, /* 67 */
4336 3, 5, 6, 3, 3, 3, 3, 12, /* 67 */
4337 12, 3, 3, 3, 7, 5, 6, 46, /* 68 */
4338 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
4339 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
4340 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
4341 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
4342 46, 46, 104, 104, 104, 104, 104, 104, /* 68 */
4343 17, 46, 46, 46, 17, 17, 17, 17, /* 68 */
4344 17, 17, 7, 7, 7, 5, 6, 16, /* 68 */
4345 107, 107, 107, 107, 107, 107, 107, 107, /* 69 */
4346 107, 107, 7, 7, 7, 5, 6, 46, /* 69 */
4347 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
4348 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
4349 4, 4, 4, 4, 4, 4, 4, 4, /* 69 */
4350 4, 4, 4, 4, 46, 46, 46, 46, /* 69 */
4351 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
4352 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
4353 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
4354 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
4355 60, 60, 60, 60, 60, 60, 60, 60, /* 70 */
4356 60, 60, 60, 60, 60, 79, 79, 79, /* 70 */
4357 79, 60, 46, 46, 46, 46, 46, 46, /* 70 */
4358 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
4359 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
4360 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
4361 15, 15, 38, 15, 15, 15, 15, 38, /* 71 */
4362 15, 15, 16, 38, 38, 38, 16, 16, /* 71 */
4363 38, 38, 38, 16, 15, 38, 15, 15, /* 71 */
4364 38, 38, 38, 38, 38, 38, 15, 15, /* 71 */
4365 15, 15, 15, 15, 38, 15, 38, 15, /* 71 */
4366 38, 15, 38, 38, 38, 38, 16, 16, /* 71 */
4367 38, 38, 15, 38, 16, 40, 40, 40, /* 71 */
4368 40, 46, 46, 46, 46, 46, 46, 46, /* 71 */
4369 46, 46, 46, 46, 46, 46, 46, 46, /* 72 */
4370 46, 46, 46, 46, 46, 46, 46, 46, /* 72 */
4371 46, 46, 46, 19, 19, 19, 19, 19, /* 72 */
4372 19, 19, 19, 19, 19, 19, 19, 108, /* 72 */
4373 109, 109, 109, 109, 109, 109, 109, 109, /* 72 */
4374 109, 109, 109, 109, 110, 110, 110, 110, /* 72 */
4375 111, 111, 111, 111, 111, 111, 111, 111, /* 72 */
4376 111, 111, 111, 111, 112, 112, 112, 112, /* 72 */
4377 113, 113, 113, 46, 46, 46, 46, 46, /* 73 */
4378 46, 46, 46, 46, 46, 46, 46, 46, /* 73 */
4379 7, 7, 7, 7, 7, 15, 15, 15, /* 73 */
4380 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
4381 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
4382 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
4383 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
4384 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
4385 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
4386 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
4387 15, 15, 7, 15, 7, 15, 15, 15, /* 74 */
4388 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
4389 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
4390 15, 15, 15, 46, 46, 46, 46, 46, /* 74 */
4391 46, 46, 46, 46, 46, 46, 46, 46, /* 74 */
4392 46, 46, 46, 46, 46, 46, 46, 46, /* 74 */
4393 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
4394 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
4395 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
4396 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
4397 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
4398 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
4399 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
4400 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
4401 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
4402 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
4403 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
4404 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
4405 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
4406 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
4407 7, 7, 46, 46, 46, 46, 46, 46, /* 76 */
4408 46, 46, 46, 46, 46, 46, 46, 46, /* 76 */
4409 15, 46, 15, 15, 15, 15, 15, 15, /* 77 */
4410 7, 7, 7, 7, 15, 15, 15, 15, /* 77 */
4411 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
4412 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
4413 7, 7, 15, 15, 15, 15, 15, 15, /* 77 */
4414 15, 5, 6, 15, 15, 15, 15, 15, /* 77 */
4415 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
4416 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
4417 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
4418 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
4419 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
4420 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
4421 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
4422 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
4423 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
4424 15, 15, 15, 46, 46, 46, 46, 46, /* 78 */
4425 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
4426 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
4427 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
4428 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
4429 15, 15, 15, 15, 15, 46, 46, 46, /* 79 */
4430 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */
4431 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */
4432 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */
4433 15, 15, 15, 15, 15, 15, 15, 15, /* 80 */
4434 15, 15, 15, 46, 46, 46, 46, 46, /* 80 */
4435 46, 46, 46, 46, 46, 46, 46, 46, /* 80 */
4436 46, 46, 46, 46, 46, 46, 46, 46, /* 80 */
4437 114, 114, 114, 114, 114, 114, 114, 114, /* 80 */
4438 114, 114, 114, 114, 114, 114, 114, 114, /* 80 */
4439 114, 114, 114, 114, 82, 82, 82, 82, /* 80 */
4440 82, 82, 82, 82, 82, 82, 82, 82, /* 80 */
4441 82, 82, 82, 82, 82, 82, 82, 82, /* 81 */
4442 115, 115, 115, 115, 115, 115, 115, 115, /* 81 */
4443 115, 115, 115, 115, 115, 115, 115, 115, /* 81 */
4444 115, 115, 115, 115, 15, 15, 15, 15, /* 81 */
4445 15, 15, 15, 15, 15, 15, 15, 15, /* 81 */
4446 15, 15, 15, 15, 15, 15, 15, 15, /* 81 */
4447 15, 15, 15, 15, 15, 15, 116, 116, /* 81 */
4448 116, 116, 116, 116, 116, 116, 116, 116, /* 81 */
4449 116, 116, 116, 116, 116, 116, 116, 116, /* 82 */
4450 116, 116, 116, 116, 116, 116, 116, 116, /* 82 */
4451 117, 117, 117, 117, 117, 117, 117, 117, /* 82 */
4452 117, 117, 117, 117, 117, 117, 117, 117, /* 82 */
4453 117, 117, 117, 117, 117, 117, 117, 117, /* 82 */
4454 117, 117, 118, 46, 46, 46, 46, 46, /* 82 */
4455 46, 46, 46, 46, 46, 46, 46, 46, /* 82 */
4456 46, 46, 46, 46, 46, 46, 46, 46, /* 82 */
4457 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
4458 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
4459 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
4460 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
4461 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
4462 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
4463 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
4464 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
4465 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
4466 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
4467 15, 15, 15, 15, 15, 15, 46, 46, /* 84 */
4468 46, 46, 46, 46, 46, 46, 46, 46, /* 84 */
4469 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
4470 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
4471 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
4472 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
4473 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
4474 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
4475 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
4476 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
4477 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
4478 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
4479 46, 46, 46, 46, 46, 46, 46, 46, /* 85 */
4480 46, 46, 46, 46, 46, 46, 46, 46, /* 85 */
4481 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
4482 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
4483 15, 15, 15, 15, 46, 46, 46, 46, /* 86 */
4484 46, 46, 15, 15, 15, 15, 15, 15, /* 86 */
4485 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
4486 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
4487 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
4488 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
4489 46, 15, 15, 15, 15, 46, 15, 15, /* 87 */
4490 15, 15, 46, 46, 15, 15, 15, 15, /* 87 */
4491 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
4492 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
4493 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
4494 46, 15, 15, 15, 15, 15, 15, 15, /* 87 */
4495 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
4496 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
4497 15, 15, 15, 15, 15, 15, 15, 15, /* 88 */
4498 15, 15, 15, 15, 46, 15, 46, 15, /* 88 */
4499 15, 15, 15, 46, 46, 46, 15, 46, /* 88 */
4500 15, 15, 15, 15, 15, 15, 15, 46, /* 88 */
4501 46, 15, 15, 15, 15, 15, 15, 15, /* 88 */
4502 46, 46, 46, 46, 46, 46, 46, 46, /* 88 */
4503 46, 46, 46, 46, 46, 46, 119, 119, /* 88 */
4504 119, 119, 119, 119, 119, 119, 119, 119, /* 88 */
4505 114, 114, 114, 114, 114, 114, 114, 114, /* 89 */
4506 114, 114, 83, 83, 83, 83, 83, 83, /* 89 */
4507 83, 83, 83, 83, 15, 46, 46, 46, /* 89 */
4508 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */
4509 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */
4510 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */
4511 46, 15, 15, 15, 15, 15, 15, 15, /* 89 */
4512 15, 15, 15, 15, 15, 15, 15, 46, /* 89 */
4513 2, 3, 3, 3, 15, 59, 3, 120, /* 90 */
4514 5, 6, 5, 6, 5, 6, 5, 6, /* 90 */
4515 5, 6, 15, 15, 5, 6, 5, 6, /* 90 */
4516 5, 6, 5, 6, 8, 5, 6, 5, /* 90 */
4517 15, 121, 121, 121, 121, 121, 121, 121, /* 90 */
4518 121, 121, 60, 60, 60, 60, 60, 60, /* 90 */
4519 8, 59, 59, 59, 59, 59, 15, 15, /* 90 */
4520 46, 46, 46, 46, 46, 46, 46, 15, /* 90 */
4521 46, 40, 40, 40, 40, 40, 40, 40, /* 91 */
4522 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
4523 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
4524 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
4525 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
4526 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
4527 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
4528 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
4529 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
4530 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
4531 40, 40, 40, 40, 40, 46, 46, 46, /* 92 */
4532 46, 60, 60, 59, 59, 59, 59, 46, /* 92 */
4533 46, 40, 40, 40, 40, 40, 40, 40, /* 92 */
4534 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
4535 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
4536 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
4537 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
4538 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
4539 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
4540 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
4541 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
4542 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
4543 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
4544 40, 40, 40, 3, 59, 59, 59, 46, /* 93 */
4545 46, 46, 46, 46, 46, 40, 40, 40, /* 94 */
4546 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
4547 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
4548 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
4549 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
4550 40, 40, 40, 40, 40, 46, 46, 46, /* 94 */
4551 46, 40, 40, 40, 40, 40, 40, 40, /* 94 */
4552 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
4553 40, 40, 40, 40, 40, 40, 40, 40, /* 95 */
4554 40, 40, 40, 40, 40, 40, 40, 46, /* 95 */
4555 15, 15, 85, 85, 85, 85, 15, 15, /* 95 */
4556 15, 15, 15, 15, 15, 15, 15, 15, /* 95 */
4557 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
4558 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
4559 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
4560 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
4561 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
4562 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
4563 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
4564 15, 15, 15, 15, 15, 46, 46, 46, /* 96 */
4565 85, 85, 85, 85, 85, 85, 85, 85, /* 96 */
4566 85, 85, 15, 15, 15, 15, 15, 15, /* 96 */
4567 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
4568 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
4569 15, 15, 15, 15, 46, 46, 46, 46, /* 97 */
4570 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */
4571 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */
4572 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */
4573 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */
4574 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */
4575 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */
4576 15, 15, 15, 15, 46, 46, 46, 15, /* 97 */
4577 114, 114, 114, 114, 114, 114, 114, 114, /* 98 */
4578 114, 114, 15, 15, 15, 15, 15, 15, /* 98 */
4579 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
4580 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
4581 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
4582 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
4583 15, 46, 46, 46, 46, 46, 46, 46, /* 98 */
4584 46, 46, 46, 46, 46, 46, 46, 46, /* 98 */
4585 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
4586 15, 15, 15, 15, 46, 46, 46, 46, /* 99 */
4587 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
4588 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
4589 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
4590 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
4591 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
4592 15, 15, 15, 15, 15, 15, 15, 46, /* 99 */
4593 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
4594 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
4595 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
4596 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
4597 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
4598 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
4599 15, 15, 15, 15, 15, 15, 15, 46, /* 100 */
4600 46, 46, 46, 15, 15, 15, 15, 15, /* 100 */
4601 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
4602 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
4603 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
4604 15, 15, 15, 15, 15, 15, 46, 46, /* 101 */
4605 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
4606 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
4607 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
4608 15, 15, 15, 15, 15, 15, 15, 46, /* 101 */
4609 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
4610 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
4611 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
4612 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
4613 40, 40, 40, 40, 40, 40, 46, 46, /* 102 */
4614 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */
4615 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */
4616 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */
4617 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
4618 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
4619 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
4620 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
4621 40, 40, 40, 40, 46, 46, 46, 46, /* 103 */
4622 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */
4623 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */
4624 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */
4625 122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
4626 122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
4627 122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
4628 122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
4629 122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
4630 122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
4631 122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
4632 122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
4633 123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
4634 123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
4635 123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
4636 123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
4637 123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
4638 123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
4639 123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
4640 123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
4641 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
4642 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
4643 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
4644 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
4645 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
4646 40, 40, 40, 40, 40, 40, 46, 46, /* 106 */
4647 46, 46, 46, 46, 46, 46, 46, 46, /* 106 */
4648 46, 46, 46, 46, 46, 46, 46, 46, /* 106 */
4649 16, 16, 16, 16, 16, 16, 16, 46, /* 107 */
4650 46, 46, 46, 46, 46, 46, 46, 46, /* 107 */
4651 46, 46, 46, 16, 16, 16, 16, 16, /* 107 */
4652 46, 46, 46, 46, 46, 46, 60, 40, /* 107 */
4653 40, 40, 40, 40, 40, 40, 40, 40, /* 107 */
4654 40, 7, 40, 40, 40, 40, 40, 40, /* 107 */
4655 40, 40, 40, 40, 40, 40, 40, 46, /* 107 */
4656 40, 40, 40, 40, 40, 46, 40, 46, /* 107 */
4657 40, 40, 46, 40, 40, 46, 40, 40, /* 108 */
4658 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
4659 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
4660 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
4661 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
4662 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
4663 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
4664 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
4665 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
4666 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
4667 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
4668 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
4669 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
4670 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
4671 40, 40, 46, 46, 46, 46, 46, 46, /* 109 */
4672 46, 46, 46, 46, 46, 46, 46, 46, /* 109 */
4673 46, 46, 46, 46, 46, 46, 46, 46, /* 110 */
4674 46, 46, 46, 46, 46, 46, 46, 46, /* 110 */
4675 46, 46, 46, 40, 40, 40, 40, 40, /* 110 */
4676 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
4677 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
4678 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
4679 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
4680 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
4681 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
4682 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
4683 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
4684 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
4685 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
4686 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
4687 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
4688 40, 40, 40, 40, 40, 40, 5, 6, /* 111 */
4689 46, 46, 46, 46, 46, 46, 46, 46, /* 112 */
4690 46, 46, 46, 46, 46, 46, 46, 46, /* 112 */
4691 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
4692 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
4693 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
4694 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
4695 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
4696 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
4697 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
4698 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
4699 46, 46, 40, 40, 40, 40, 40, 40, /* 113 */
4700 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
4701 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
4702 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
4703 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
4704 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
4705 40, 40, 40, 40, 40, 40, 40, 40, /* 114 */
4706 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
4707 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
4708 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
4709 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
4710 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
4711 40, 40, 40, 40, 40, 40, 40, 40, /* 114 */
4712 40, 40, 40, 40, 46, 46, 46, 46, /* 114 */
4713 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
4714 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
4715 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
4716 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
4717 60, 60, 60, 60, 46, 46, 46, 46, /* 115 */
4718 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
4719 3, 8, 8, 12, 12, 5, 6, 5, /* 115 */
4720 6, 5, 6, 5, 6, 5, 6, 5, /* 115 */
4721 6, 5, 6, 5, 6, 46, 46, 46, /* 116 */
4722 46, 3, 3, 3, 3, 12, 12, 12, /* 116 */
4723 3, 3, 3, 46, 3, 3, 3, 3, /* 116 */
4724 8, 5, 6, 5, 6, 5, 6, 3, /* 116 */
4725 3, 3, 7, 8, 7, 7, 7, 46, /* 116 */
4726 3, 4, 3, 3, 46, 46, 46, 46, /* 116 */
4727 40, 40, 40, 46, 40, 46, 40, 40, /* 116 */
4728 40, 40, 40, 40, 40, 40, 40, 40, /* 116 */
4729 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
4730 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
4731 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
4732 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
4733 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
4734 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
4735 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
4736 40, 40, 40, 40, 40, 46, 46, 104, /* 117 */
4737 46, 3, 3, 3, 4, 3, 3, 3, /* 118 */
4738 5, 6, 3, 7, 3, 8, 3, 3, /* 118 */
4739 9, 9, 9, 9, 9, 9, 9, 9, /* 118 */
4740 9, 9, 3, 3, 7, 7, 7, 3, /* 118 */
4741 3, 10, 10, 10, 10, 10, 10, 10, /* 118 */
4742 10, 10, 10, 10, 10, 10, 10, 10, /* 118 */
4743 10, 10, 10, 10, 10, 10, 10, 10, /* 118 */
4744 10, 10, 10, 5, 3, 6, 11, 12, /* 118 */
4745 11, 13, 13, 13, 13, 13, 13, 13, /* 119 */
4746 13, 13, 13, 13, 13, 13, 13, 13, /* 119 */
4747 13, 13, 13, 13, 13, 13, 13, 13, /* 119 */
4748 13, 13, 13, 5, 7, 6, 7, 46, /* 119 */
4749 46, 3, 5, 6, 3, 3, 40, 40, /* 119 */
4750 40, 40, 40, 40, 40, 40, 40, 40, /* 119 */
4751 59, 40, 40, 40, 40, 40, 40, 40, /* 119 */
4752 40, 40, 40, 40, 40, 40, 40, 40, /* 119 */
4753 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
4754 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
4755 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
4756 40, 40, 40, 40, 40, 40, 59, 59, /* 120 */
4757 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
4758 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
4759 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
4760 40, 40, 40, 40, 40, 40, 40, 46, /* 120 */
4761 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */
4762 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */
4763 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */
4764 46, 46, 40, 40, 40, 46, 46, 46, /* 121 */
4765 4, 4, 7, 11, 15, 4, 4, 46, /* 121 */
4766 7, 7, 7, 7, 7, 15, 15, 46, /* 121 */
4767 46, 46, 46, 46, 46, 46, 46, 46, /* 121 */
4768 46, 46, 46, 46, 46, 15, 46, 46 /* 121 */
4771 /* The A table has 124 entries for a total of 496 bytes. */
4773 const uint32 js_A
[] = {
4774 0x0001000F, /* 0 Cc, ignorable */
4775 0x0004000F, /* 1 Cc, whitespace */
4776 0x0004000C, /* 2 Zs, whitespace */
4777 0x00000018, /* 3 Po */
4778 0x0006001A, /* 4 Sc, currency */
4779 0x00000015, /* 5 Ps */
4780 0x00000016, /* 6 Pe */
4781 0x00000019, /* 7 Sm */
4782 0x00000014, /* 8 Pd */
4783 0x00036089, /* 9 Nd, identifier part, decimal 16 */
4784 0x0827FF81, /* 10 Lu, hasLower (add 32), identifier start, supradecimal 31 */
4785 0x0000001B, /* 11 Sk */
4786 0x00050017, /* 12 Pc, underscore */
4787 0x0817FF82, /* 13 Ll, hasUpper (subtract 32), identifier start, supradecimal 31 */
4788 0x0000000C, /* 14 Zs */
4789 0x0000001C, /* 15 So */
4790 0x00070182, /* 16 Ll, identifier start */
4791 0x0000600B, /* 17 No, decimal 16 */
4792 0x0000500B, /* 18 No, decimal 8 */
4793 0x0000800B, /* 19 No, strange */
4794 0x08270181, /* 20 Lu, hasLower (add 32), identifier start */
4795 0x08170182, /* 21 Ll, hasUpper (subtract 32), identifier start */
4796 0xE1D70182, /* 22 Ll, hasUpper (subtract -121), identifier start */
4797 0x00670181, /* 23 Lu, hasLower (add 1), identifier start */
4798 0x00570182, /* 24 Ll, hasUpper (subtract 1), identifier start */
4799 0xCE670181, /* 25 Lu, hasLower (add -199), identifier start */
4800 0x3A170182, /* 26 Ll, hasUpper (subtract 232), identifier start */
4801 0xE1E70181, /* 27 Lu, hasLower (add -121), identifier start */
4802 0x4B170182, /* 28 Ll, hasUpper (subtract 300), identifier start */
4803 0x34A70181, /* 29 Lu, hasLower (add 210), identifier start */
4804 0x33A70181, /* 30 Lu, hasLower (add 206), identifier start */
4805 0x33670181, /* 31 Lu, hasLower (add 205), identifier start */
4806 0x32A70181, /* 32 Lu, hasLower (add 202), identifier start */
4807 0x32E70181, /* 33 Lu, hasLower (add 203), identifier start */
4808 0x33E70181, /* 34 Lu, hasLower (add 207), identifier start */
4809 0x34E70181, /* 35 Lu, hasLower (add 211), identifier start */
4810 0x34670181, /* 36 Lu, hasLower (add 209), identifier start */
4811 0x35670181, /* 37 Lu, hasLower (add 213), identifier start */
4812 0x00070181, /* 38 Lu, identifier start */
4813 0x36A70181, /* 39 Lu, hasLower (add 218), identifier start */
4814 0x00070185, /* 40 Lo, identifier start */
4815 0x36670181, /* 41 Lu, hasLower (add 217), identifier start */
4816 0x36E70181, /* 42 Lu, hasLower (add 219), identifier start */
4817 0x00AF0181, /* 43 Lu, hasLower (add 2), hasTitle, identifier start */
4818 0x007F0183, /* 44 Lt, hasUpper (subtract 1), hasLower (add 1), hasTitle, identifier start */
4819 0x009F0182, /* 45 Ll, hasUpper (subtract 2), hasTitle, identifier start */
4820 0x00000000, /* 46 unassigned */
4821 0x34970182, /* 47 Ll, hasUpper (subtract 210), identifier start */
4822 0x33970182, /* 48 Ll, hasUpper (subtract 206), identifier start */
4823 0x33570182, /* 49 Ll, hasUpper (subtract 205), identifier start */
4824 0x32970182, /* 50 Ll, hasUpper (subtract 202), identifier start */
4825 0x32D70182, /* 51 Ll, hasUpper (subtract 203), identifier start */
4826 0x33D70182, /* 52 Ll, hasUpper (subtract 207), identifier start */
4827 0x34570182, /* 53 Ll, hasUpper (subtract 209), identifier start */
4828 0x34D70182, /* 54 Ll, hasUpper (subtract 211), identifier start */
4829 0x35570182, /* 55 Ll, hasUpper (subtract 213), identifier start */
4830 0x36970182, /* 56 Ll, hasUpper (subtract 218), identifier start */
4831 0x36570182, /* 57 Ll, hasUpper (subtract 217), identifier start */
4832 0x36D70182, /* 58 Ll, hasUpper (subtract 219), identifier start */
4833 0x00070084, /* 59 Lm, identifier start */
4834 0x00030086, /* 60 Mn, identifier part */
4835 0x09A70181, /* 61 Lu, hasLower (add 38), identifier start */
4836 0x09670181, /* 62 Lu, hasLower (add 37), identifier start */
4837 0x10270181, /* 63 Lu, hasLower (add 64), identifier start */
4838 0x0FE70181, /* 64 Lu, hasLower (add 63), identifier start */
4839 0x09970182, /* 65 Ll, hasUpper (subtract 38), identifier start */
4840 0x09570182, /* 66 Ll, hasUpper (subtract 37), identifier start */
4841 0x10170182, /* 67 Ll, hasUpper (subtract 64), identifier start */
4842 0x0FD70182, /* 68 Ll, hasUpper (subtract 63), identifier start */
4843 0x0F970182, /* 69 Ll, hasUpper (subtract 62), identifier start */
4844 0x0E570182, /* 70 Ll, hasUpper (subtract 57), identifier start */
4845 0x0BD70182, /* 71 Ll, hasUpper (subtract 47), identifier start */
4846 0x0D970182, /* 72 Ll, hasUpper (subtract 54), identifier start */
4847 0x15970182, /* 73 Ll, hasUpper (subtract 86), identifier start */
4848 0x14170182, /* 74 Ll, hasUpper (subtract 80), identifier start */
4849 0x14270181, /* 75 Lu, hasLower (add 80), identifier start */
4850 0x0C270181, /* 76 Lu, hasLower (add 48), identifier start */
4851 0x0C170182, /* 77 Ll, hasUpper (subtract 48), identifier start */
4852 0x00034089, /* 78 Nd, identifier part, decimal 0 */
4853 0x00000087, /* 79 Me */
4854 0x00030088, /* 80 Mc, identifier part */
4855 0x00037489, /* 81 Nd, identifier part, decimal 26 */
4856 0x00005A0B, /* 82 No, decimal 13 */
4857 0x00006E0B, /* 83 No, decimal 23 */
4858 0x0000740B, /* 84 No, decimal 26 */
4859 0x0000000B, /* 85 No */
4860 0xFE170182, /* 86 Ll, hasUpper (subtract -8), identifier start */
4861 0xFE270181, /* 87 Lu, hasLower (add -8), identifier start */
4862 0xED970182, /* 88 Ll, hasUpper (subtract -74), identifier start */
4863 0xEA970182, /* 89 Ll, hasUpper (subtract -86), identifier start */
4864 0xE7170182, /* 90 Ll, hasUpper (subtract -100), identifier start */
4865 0xE0170182, /* 91 Ll, hasUpper (subtract -128), identifier start */
4866 0xE4170182, /* 92 Ll, hasUpper (subtract -112), identifier start */
4867 0xE0970182, /* 93 Ll, hasUpper (subtract -126), identifier start */
4868 0xFDD70182, /* 94 Ll, hasUpper (subtract -9), identifier start */
4869 0xEDA70181, /* 95 Lu, hasLower (add -74), identifier start */
4870 0xFDE70181, /* 96 Lu, hasLower (add -9), identifier start */
4871 0xEAA70181, /* 97 Lu, hasLower (add -86), identifier start */
4872 0xE7270181, /* 98 Lu, hasLower (add -100), identifier start */
4873 0xFE570182, /* 99 Ll, hasUpper (subtract -7), identifier start */
4874 0xE4270181, /* 100 Lu, hasLower (add -112), identifier start */
4875 0xFE670181, /* 101 Lu, hasLower (add -7), identifier start */
4876 0xE0270181, /* 102 Lu, hasLower (add -128), identifier start */
4877 0xE0A70181, /* 103 Lu, hasLower (add -126), identifier start */
4878 0x00010010, /* 104 Cf, ignorable */
4879 0x0004000D, /* 105 Zl, whitespace */
4880 0x0004000E, /* 106 Zp, whitespace */
4881 0x0000400B, /* 107 No, decimal 0 */
4882 0x0000440B, /* 108 No, decimal 2 */
4883 0x0427438A, /* 109 Nl, hasLower (add 16), identifier start, decimal 1 */
4884 0x0427818A, /* 110 Nl, hasLower (add 16), identifier start, strange */
4885 0x0417638A, /* 111 Nl, hasUpper (subtract 16), identifier start, decimal 17 */
4886 0x0417818A, /* 112 Nl, hasUpper (subtract 16), identifier start, strange */
4887 0x0007818A, /* 113 Nl, identifier start, strange */
4888 0x0000420B, /* 114 No, decimal 1 */
4889 0x0000720B, /* 115 No, decimal 25 */
4890 0x06A0001C, /* 116 So, hasLower (add 26) */
4891 0x0690001C, /* 117 So, hasUpper (subtract 26) */
4892 0x00006C0B, /* 118 No, decimal 22 */
4893 0x0000560B, /* 119 No, decimal 11 */
4894 0x0007738A, /* 120 Nl, identifier start, decimal 25 */
4895 0x0007418A, /* 121 Nl, identifier start, decimal 0 */
4896 0x00000013, /* 122 Cs */
4897 0x00000012 /* 123 Co */
4900 const jschar js_uriReservedPlusPound_ucstr
[] =
4901 {';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#', 0};
4902 const jschar js_uriUnescaped_ucstr
[] =
4903 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
4904 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
4905 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
4906 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
4907 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
4908 '-', '_', '.', '!', '~', '*', '\'', '(', ')', 0};
4910 #define URI_CHUNK 64U
4912 /* Concatenate jschars onto the buffer */
4914 AddCharsToURI(JSContext
*cx
, JSCharBuffer
*buf
,
4915 const jschar
*chars
, size_t length
)
4920 total
= buf
->length
+ length
+ 1;
4922 JS_HOWMANY(total
, URI_CHUNK
) > JS_HOWMANY(buf
->length
+ 1, URI_CHUNK
)) {
4923 total
= JS_ROUNDUP(total
, URI_CHUNK
);
4924 newchars
= (jschar
*) JS_realloc(cx
, buf
->chars
,
4925 total
* sizeof(jschar
));
4928 buf
->chars
= newchars
;
4930 js_strncpy(buf
->chars
+ buf
->length
, chars
, length
);
4931 buf
->length
+= length
;
4932 buf
->chars
[buf
->length
] = 0;
4937 TransferBufferToString(JSContext
*cx
, JSCharBuffer
*cb
, jsval
*rval
)
4944 * Shrinking realloc can fail (e.g., with a BSD-style allocator), but we
4945 * don't worry about that case here.
4948 chars
= (jschar
*) JS_realloc(cx
, cb
->chars
, (n
+ 1) * sizeof(jschar
));
4951 str
= js_NewString(cx
, chars
, n
);
4955 /* Successful allocation transfer ownership of cb->chars to the string. */
4957 memset(cb
, JS_FREE_PATTERN
, sizeof *cb
);
4960 *rval
= STRING_TO_JSVAL(str
);
4965 * ECMA 3, 15.1.3 URI Handling Function Properties
4967 * The following are implementations of the algorithms
4968 * given in the ECMA specification for the hidden functions
4969 * 'Encode' and 'Decode'.
4972 Encode(JSContext
*cx
, JSString
*str
, const jschar
*unescapedSet
,
4973 const jschar
*unescapedSet2
, jsval
*rval
)
4975 size_t length
, j
, k
, L
;
4977 jschar
*chars
, c
, c2
;
4981 static const char HexDigits
[] = "0123456789ABCDEF"; /* NB: uppercase */
4983 JSSTRING_CHARS_AND_LENGTH(str
, chars
, length
);
4985 *rval
= STRING_TO_JSVAL(cx
->runtime
->emptyString
);
4992 /* From this point the control must goto bad on failures. */
4995 for (k
= 0; k
< length
; k
++) {
4997 if (js_strchr(unescapedSet
, c
) ||
4998 (unescapedSet2
&& js_strchr(unescapedSet2
, c
))) {
4999 if (!AddCharsToURI(cx
, &cb
, &c
, 1))
5002 if ((c
>= 0xDC00) && (c
<= 0xDFFF)) {
5003 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
5004 JSMSG_BAD_URI
, NULL
);
5007 if (c
< 0xD800 || c
> 0xDBFF) {
5012 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
5013 JSMSG_BAD_URI
, NULL
);
5017 if ((c2
< 0xDC00) || (c2
> 0xDFFF)) {
5018 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
5019 JSMSG_BAD_URI
, NULL
);
5022 v
= ((c
- 0xD800) << 10) + (c2
- 0xDC00) + 0x10000;
5024 L
= js_OneUcs4ToUtf8Char(utf8buf
, v
);
5025 for (j
= 0; j
< L
; j
++) {
5026 hexBuf
[1] = HexDigits
[utf8buf
[j
] >> 4];
5027 hexBuf
[2] = HexDigits
[utf8buf
[j
] & 0xf];
5028 if (!AddCharsToURI(cx
, &cb
, hexBuf
, 3))
5034 if (!TransferBufferToString(cx
, &cb
, rval
))
5040 JS_free(cx
, cb
.chars
);
5045 Decode(JSContext
*cx
, JSString
*str
, const jschar
*reservedSet
, jsval
*rval
)
5047 size_t length
, start
, k
;
5049 jschar
*chars
, c
, H
;
5055 JSSTRING_CHARS_AND_LENGTH(str
, chars
, length
);
5057 *rval
= STRING_TO_JSVAL(cx
->runtime
->emptyString
);
5064 /* From this point the control must goto bad on failures. */
5065 for (k
= 0; k
< length
; k
++) {
5069 if ((k
+ 2) >= length
)
5070 goto report_bad_uri
;
5071 if (!JS7_ISHEX(chars
[k
+1]) || !JS7_ISHEX(chars
[k
+2]))
5072 goto report_bad_uri
;
5073 B
= JS7_UNHEX(chars
[k
+1]) * 16 + JS7_UNHEX(chars
[k
+2]);
5079 while (B
& (0x80 >> n
))
5081 if (n
== 1 || n
> 6)
5082 goto report_bad_uri
;
5083 octets
[0] = (uint8
)B
;
5084 if (k
+ 3 * (n
- 1) >= length
)
5085 goto report_bad_uri
;
5086 for (j
= 1; j
< n
; j
++) {
5088 if (chars
[k
] != '%')
5089 goto report_bad_uri
;
5090 if (!JS7_ISHEX(chars
[k
+1]) || !JS7_ISHEX(chars
[k
+2]))
5091 goto report_bad_uri
;
5092 B
= JS7_UNHEX(chars
[k
+1]) * 16 + JS7_UNHEX(chars
[k
+2]);
5093 if ((B
& 0xC0) != 0x80)
5094 goto report_bad_uri
;
5096 octets
[j
] = (char)B
;
5098 v
= Utf8ToOneUcs4Char(octets
, n
);
5102 goto report_bad_uri
;
5103 c
= (jschar
)((v
& 0x3FF) + 0xDC00);
5104 H
= (jschar
)((v
>> 10) + 0xD800);
5105 if (!AddCharsToURI(cx
, &cb
, &H
, 1))
5111 if (js_strchr(reservedSet
, c
)) {
5112 if (!AddCharsToURI(cx
, &cb
, &chars
[start
], (k
- start
+ 1)))
5115 if (!AddCharsToURI(cx
, &cb
, &c
, 1))
5119 if (!AddCharsToURI(cx
, &cb
, &c
, 1))
5124 if (!TransferBufferToString(cx
, &cb
, rval
))
5130 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_BAD_URI
);
5134 JS_free(cx
, cb
.chars
);
5139 str_decodeURI(JSContext
*cx
, uintN argc
, jsval
*vp
)
5143 str
= ArgToRootedString(cx
, argc
, vp
, 0);
5146 return Decode(cx
, str
, js_uriReservedPlusPound_ucstr
, vp
);
5150 str_decodeURI_Component(JSContext
*cx
, uintN argc
, jsval
*vp
)
5154 str
= ArgToRootedString(cx
, argc
, vp
, 0);
5157 return Decode(cx
, str
, js_empty_ucstr
, vp
);
5161 str_encodeURI(JSContext
*cx
, uintN argc
, jsval
*vp
)
5165 str
= ArgToRootedString(cx
, argc
, vp
, 0);
5168 return Encode(cx
, str
, js_uriReservedPlusPound_ucstr
, js_uriUnescaped_ucstr
,
5173 str_encodeURI_Component(JSContext
*cx
, uintN argc
, jsval
*vp
)
5177 str
= ArgToRootedString(cx
, argc
, vp
, 0);
5180 return Encode(cx
, str
, js_uriUnescaped_ucstr
, NULL
, vp
);
5184 * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
5185 * least 6 bytes long. Return the number of UTF-8 bytes of data written.
5188 js_OneUcs4ToUtf8Char(uint8
*utf8Buffer
, uint32 ucs4Char
)
5192 JS_ASSERT(ucs4Char
<= 0x7FFFFFFF);
5193 if (ucs4Char
< 0x80) {
5194 *utf8Buffer
= (uint8
)ucs4Char
;
5197 uint32 a
= ucs4Char
>> 11;
5205 utf8Buffer
[i
] = (uint8
)((ucs4Char
& 0x3F) | 0x80);
5208 *utf8Buffer
= (uint8
)(0x100 - (1 << (8-utf8Length
)) + ucs4Char
);
5214 * Convert a utf8 character sequence into a UCS-4 character and return that
5215 * character. It is assumed that the caller already checked that the sequence
5219 Utf8ToOneUcs4Char(const uint8
*utf8Buffer
, int utf8Length
)
5223 /* from Unicode 3.1, non-shortest form is illegal */
5224 static const uint32 minucs4Table
[] = {
5225 0x00000080, 0x00000800, 0x0001000, 0x0020000, 0x0400000
5228 JS_ASSERT(utf8Length
>= 1 && utf8Length
<= 6);
5229 if (utf8Length
== 1) {
5230 ucs4Char
= *utf8Buffer
;
5231 JS_ASSERT(!(ucs4Char
& 0x80));
5233 JS_ASSERT((*utf8Buffer
& (0x100 - (1 << (7-utf8Length
)))) ==
5234 (0x100 - (1 << (8-utf8Length
))));
5235 ucs4Char
= *utf8Buffer
++ & ((1<<(7-utf8Length
))-1);
5236 minucs4Char
= minucs4Table
[utf8Length
-2];
5237 while (--utf8Length
) {
5238 JS_ASSERT((*utf8Buffer
& 0xC0) == 0x80);
5239 ucs4Char
= ucs4Char
<<6 | (*utf8Buffer
++ & 0x3F);
5241 if (ucs4Char
< minucs4Char
||
5242 ucs4Char
== 0xFFFE || ucs4Char
== 0xFFFF) {
5249 #if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
5251 JS_FRIEND_API(size_t)
5252 js_PutEscapedStringImpl(char *buffer
, size_t bufferSize
, FILE *fp
,
5253 JSString
*str
, uint32 quote
)
5255 jschar
*chars
, *charsEnd
;
5259 uintN u
, hex
, shift
;
5261 STOP
, FIRST_QUOTE
, LAST_QUOTE
, CHARS
, ESCAPE_START
, ESCAPE_MORE
5264 JS_ASSERT(quote
== 0 || quote
== '\'' || quote
== '"');
5265 JS_ASSERT_IF(buffer
, bufferSize
!= 0);
5266 JS_ASSERT_IF(!buffer
, bufferSize
== 0);
5267 JS_ASSERT_IF(fp
, !buffer
);
5269 JSSTRING_CHARS_AND_END(str
, chars
, charsEnd
);
5272 state
= FIRST_QUOTE
;
5276 c
= 0; /* to quell GCC warnings */
5293 if (chars
== charsEnd
) {
5300 escape
= strchr(js_EscapeMap
, (int)u
);
5309 if (u
== quote
|| u
== '\\')
5312 } else if (u
< 0x100) {
5327 state
= ESCAPE_START
;
5330 JS_ASSERT(' ' <= u
&& u
< 127);
5332 state
= ESCAPE_MORE
;
5340 u
= 0xF & (hex
>> shift
);
5341 c
= (char)(u
+ (u
< 10 ? '0' : 'A' - 10));
5345 if (n
== bufferSize
)