StringObject.cpp

Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is [Open Source Virtual Machine.].
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Adobe System Incorporated.
00018  * Portions created by the Initial Developer are Copyright (C) 2004-2006
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Adobe AS3 Team
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "avmplus.h"
00039 
00040 namespace avmplus
00041 {
00042     using namespace MMgc;
00043 
00044     int String::Length(const wchar *str)
00045     {
00046         if (!str) 
00047             return 0;
00048 
00049         int len = 0;
00050         while (*str) {
00051             len++;
00052             str++;
00053         }
00054         return len;
00055     }
00056 
00057     int String::Length(const char *str)
00058     {
00059         if (!str) 
00060             return 0;
00061 
00062         int len = 0;
00063         while (*str) {
00064             len++;
00065             str++;
00066         }
00067         return len;
00068     }
00069 
00070     // create empty string ready to be filled in
00071     String::String(int len) 
00072 #ifdef DEBUGGER
00073         : AvmPlusScriptableObject(kStringType)
00074 #endif // DEBUGGER
00075     {
00076         AvmAssert(len >= 0);
00077         MMGC_MEM_TYPE(this);
00078         setBuf(allocBuf(len));
00079         m_length = len;
00080     }
00081 
00082     // decode utf8 
00083     String::String(const char *str, int utf8len, int utf16len)
00084 #ifdef DEBUGGER
00085         : AvmPlusScriptableObject(kStringType)
00086 #endif // DEBUGGER
00087     {
00088         AvmAssert(utf8len >= 0);
00089         AvmAssert(utf16len >= 0);
00090 
00091         MMGC_MEM_TYPE(this);
00092         setBuf(allocBuf(utf16len));
00093         m_length = UnicodeUtils::Utf8ToUtf16((const uint8 *)str, utf8len,
00094                                              getData(), utf16len);
00095         AvmAssert(m_length >= 0);
00096         getData()[m_length] = 0;
00097     }
00098 
00099     // convert c-style wstring to String
00100     String::String(const wchar *str, int len)
00101 #ifdef DEBUGGER
00102         : AvmPlusScriptableObject(kStringType)
00103 #endif // DEBUGGER
00104     {
00105         AvmAssert(len >= 0);
00106         m_length = len;
00107         MMGC_MEM_TYPE(this);
00108         setBuf(allocBuf(m_length));
00109         memcpy (getData(), str, m_length * sizeof(wchar));
00110         getData()[m_length] = 0;
00111     }
00112 
00113     // concat
00114     String::String(Stringp s1, Stringp s2)
00115 #ifdef DEBUGGER
00116         : AvmPlusScriptableObject(kStringType)
00117 #endif // DEBUGGER
00118     {
00119         m_length = s1->length() + s2->length();
00120         AvmAssert(m_length >= 0);
00121         setPrefixOrOffsetOrNumber(uintptr(s1) | PREFIXFLAG);
00122         if (s2->needsNormalization()) s2->normalize();
00123         setBuf(s2->m_buf);
00124     }
00125 
00126     // substr
00127     String::String(Stringp s, int pos, int len)
00128 #ifdef DEBUGGER
00129         : AvmPlusScriptableObject(kStringType)
00130 #endif // DEBUGGER
00131     {
00132         // out-of-bounds requests return sensible things
00133         if (pos < 0) {
00134             pos = 0;
00135         }
00136         if (len < 0) {
00137             len = 0;
00138         }
00139 
00140         int s_len = s->length();
00141         if (pos + len > s_len) {
00142             len = s_len - pos;
00143         }
00144         if (pos > s_len) {
00145             len = 0;
00146         }
00147 
00148         AvmAssert(pos >= 0);
00149         AvmAssert(len == 0 || pos + len <= s_len);
00150 
00151         #if 0 // old way
00152         if (s->hasPrefix()) s->normalize();
00153 
00154         m_length = len;
00155         GC* gc = GC::GetGC(this);
00156         MMGC_MEM_TYPE(this);
00157         m_buf = (wchar *) gc->Alloc (sizeof(wchar)*(m_length+1), 0);
00158         memcpy (m_buf, s->m_buf+pos, m_length * sizeof(wchar));
00159         m_buf[m_length] = 0;
00160         m_prefixOrOffsetOrNumber = 0;
00161         #endif
00162 
00163         if (s->hasOffset())
00164         {
00165             m_length = len;
00166             setBuf(s->m_buf);
00167             m_prefixOrOffsetOrNumber = int(((s->getOffset() + pos) << 2) | OFFSETFLAG);
00168             return;
00169         }
00170         else if (s->hasPrefix())
00171         {
00172             Stringp news = s;
00173             while (news->getPrefix() && pos < news->getPrefix()->length())
00174                 news = news->getPrefix();
00175 
00176             int newpos = pos;
00177             int segmentLen = news->length();
00178             if (news->getPrefix())
00179             {
00180                 int prefixLen = news->getPrefix()->length();
00181                 newpos -= prefixLen;
00182                 segmentLen -= prefixLen;
00183             }
00184 
00185             // If our substring is completely contained within our prefix
00186             // string, we can just use that string.  Otherwise we need
00187             // to normalize our string and generate an offset from the
00188             // new string.
00189             if ((newpos + len) <= segmentLen)
00190             {
00191                 m_length = len;
00192                 setBuf(news->m_buf);
00193                 int offset = news->getOffset() + newpos;
00194                 m_prefixOrOffsetOrNumber = int((offset << 2) | OFFSETFLAG);
00195                 return;
00196             }
00197 
00198             s->normalize();
00199         }
00200 
00201         m_length = len;
00202         setBuf(s->m_buf);
00203         m_prefixOrOffsetOrNumber = int((pos << 2) | OFFSETFLAG);
00204     }
00205                               
00206     // compare (dst,len) to (src,len), including nulls
00207     int String::Compare(const wchar *dst, int dstLen, const wchar *src, int srcLen)
00208     {
00209         int ret = 0;
00210         int count = (dstLen < srcLen) ? dstLen : srcLen;  // choose smaller of two
00211         const wchar *dstend = dst + count;
00212 
00213         while(dst < dstend && 0 == (ret = (int)(*src - *dst)))
00214         {
00215             ++src, ++dst;
00216         }
00217 
00218         // catch substring cases (e.g. '1' vs. '104')
00219         if (ret == 0)
00220         {
00221             if (srcLen < dstLen)
00222                 ret = -1;
00223             else if (srcLen > dstLen)
00224                 ret = 1;
00225             else
00226                 ; // really equal
00227         }
00228         return ret;
00229     }
00230 
00231     // compare (dst,len) to (src), src is null-terminated 8bit string
00232     int String::Compare(const wchar *dst, const char *src, int len)
00233     {
00234         int   ret = 0;
00235         const wchar *dstend = dst + len;
00236 
00237         while(dst < dstend && *src && 0 == (ret = (int)(((wchar)*src) - *dst)) )
00238         {
00239             ++src, ++dst;
00240         }
00241 
00242         if (ret == 0)
00243         {
00244             // catch substring cases (e.g. '1' vs. '104')
00245             if (dst < dstend)
00246             {
00247                 // more chars in dst than src
00248                 AvmAssert(*src == 0);
00249                 ret = -1;
00250             }
00251             else if (*src)
00252             {
00253                 // more chars in src than dst
00254                 AvmAssert(dst == dstend);
00255                 ret = 1;
00256             }
00257             else
00258             {
00259                 // really equal
00260                 AvmAssert(dst == dstend);
00261                 AvmAssert(*src == 0);
00262             }
00263         }
00264 
00265         return ret;
00266     }
00267 
00268     bool String::Contains(wchar c)
00269     {
00270         if (hasPrefix()) normalize();
00271 
00272         const wchar *p = getData() + getOffset();
00273 
00274         while (*p && (*p != c)) {
00275             p++;
00276         }
00277 
00278         return (*p == c);
00279     }
00280 
00281     // flatten a composite string
00282     void String::normalize()
00283     {
00284         AvmAssert(needsNormalization() == true);
00285         MMGC_MEM_TYPE(this);
00286         StringBuf *newData = allocBuf(length());
00287         if (newData == NULL)
00288             return;
00289         wchar *new_buf = newData->m_buf;
00290         new_buf[length()] = 0;
00291 
00292         if (hasPrefix())
00293         {
00294             // copy suffix strings right to left
00295             Stringp p = this;
00296             for (; p->getPrefix() != 0; p = p->getPrefix())
00297             {
00298                 memcpy(new_buf + p->getPrefix()->length(), p->getData(), sizeof(wchar)*(p->length()-p->getPrefix()->length()));
00299             }
00300 
00301             memcpy(new_buf, p->getData() + p->getOffset(), sizeof(wchar) * p->length());
00302             setBuf(newData);
00303         }
00304         else
00305         {
00306             AvmAssert(hasOffset());
00307             memcpy(new_buf, getData() + getOffset(), sizeof(wchar) * length());
00308             setBuf(newData);
00309         }
00310 
00311         // prefix is left for GC to dispose of
00312         setPrefixOrOffsetOrNumber(0);
00313     }
00314 
00315     // encode utf8
00316     UTF8String* String::toUTF8String()
00317     {
00318         if (hasPrefix()) normalize();
00319         int utf8len = UnicodeUtils::Utf16ToUtf8(getData() + getOffset(), length(), NULL, 0);
00320 
00321         if( utf8len < 0 )
00322         {
00323             utf8len = 0;
00324         }
00325 
00326         UTF8String* out = new (GC::GetGC(this), utf8len) UTF8String(utf8len);
00327         
00328         if (out) {
00329             char *dst = out->lockBuffer();
00330             UnicodeUtils::Utf16ToUtf8(getData() + getOffset(), length(), (uint8*)dst, utf8len);
00331             dst[utf8len] = 0;
00332             out->unlockBuffer();
00333         }
00334         return out;
00335     }
00336 
00337     //
00338     // uppercase/lowercase conversion
00339     //
00340 
00341     const wchar String::lowerCaseBase[] = 
00342         {
00343             0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
00344             0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
00345             0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x00B5, 0x00E0, 0x00E1, 0x00E2,
00346             0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC,
00347             0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6,
00348             0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0101, 0x0103,
00349             0x0105, 0x0107, 0x0109, 0x010B, 0x010D, 0x010F, 0x0111, 0x0113, 0x0115, 0x0117,
00350             0x0119, 0x011B, 0x011D, 0x011F, 0x0121, 0x0123, 0x0125, 0x0127, 0x0129, 0x012B,
00351             0x012D, 0x012F, 0x0131, 0x0133, 0x0135, 0x0137, 0x013A, 0x013C, 0x013E, 0x0140,
00352             0x0142, 0x0144, 0x0146, 0x0148, 0x014B, 0x014D, 0x014F, 0x0151, 0x0153, 0x0155,
00353             0x0157, 0x0159, 0x015B, 0x015D, 0x015F, 0x0161, 0x0163, 0x0165, 0x0167, 0x0169,
00354             0x016B, 0x016D, 0x016F, 0x0171, 0x0173, 0x0175, 0x0177, 0x017A, 0x017C, 0x017E,
00355             0x017F, 0x0183, 0x0185, 0x0188, 0x018C, 0x0192, 0x0195, 0x0199, 0x01A1, 0x01A3,
00356             0x01A5, 0x01A8, 0x01AD, 0x01B0, 0x01B4, 0x01B6, 0x01B9, 0x01BD, 0x01BF, 0x01C5,
00357             0x01C6, 0x01C8, 0x01C9, 0x01CB, 0x01CC, 0x01CE, 0x01D0, 0x01D2, 0x01D4, 0x01D6,
00358             0x01D8, 0x01DA, 0x01DC, 0x01DD, 0x01DF, 0x01E1, 0x01E3, 0x01E5, 0x01E7, 0x01E9,
00359             0x01EB, 0x01ED, 0x01EF, 0x01F2, 0x01F3, 0x01F5, 0x01F9, 0x01FB, 0x01FD, 0x01FF,
00360             0x0201, 0x0203, 0x0205, 0x0207, 0x0209, 0x020B, 0x020D, 0x020F, 0x0211, 0x0213,
00361             0x0215, 0x0217, 0x0219, 0x021B, 0x021D, 0x021F, 0x0223, 0x0225, 0x0227, 0x0229,
00362             0x022B, 0x022D, 0x022F, 0x0231, 0x0233, 0x0253, 0x0254, 0x0256, 0x0257, 0x0259,
00363             0x025B, 0x0260, 0x0263, 0x0268, 0x0269, 0x026F, 0x0272, 0x0275, 0x0280, 0x0283,
00364             0x0288, 0x028A, 0x028B, 0x0292, 0x0345, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03B1,
00365             0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB,
00366             0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5,
00367             0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03D0,
00368             0x03D1, 0x03D5, 0x03D6, 0x03DB, 0x03DD, 0x03DF, 0x03E1, 0x03E3, 0x03E5, 0x03E7,
00369             0x03E9, 0x03EB, 0x03ED, 0x03EF, 0x03F0, 0x03F1, 0x03F2, 0x03F5, 0x0430, 0x0431,
00370             0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B,
00371             0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
00372             0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
00373             0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459,
00374             0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F, 0x0461, 0x0463, 0x0465, 0x0467,
00375             0x0469, 0x046B, 0x046D, 0x046F, 0x0471, 0x0473, 0x0475, 0x0477, 0x0479, 0x047B,
00376             0x047D, 0x047F, 0x0481, 0x048D, 0x048F, 0x0491, 0x0493, 0x0495, 0x0497, 0x0499,
00377             0x049B, 0x049D, 0x049F, 0x04A1, 0x04A3, 0x04A5, 0x04A7, 0x04A9, 0x04AB, 0x04AD,
00378             0x04AF, 0x04B1, 0x04B3, 0x04B5, 0x04B7, 0x04B9, 0x04BB, 0x04BD, 0x04BF, 0x04C2,
00379             0x04C4, 0x04C8, 0x04CC, 0x04D1, 0x04D3, 0x04D5, 0x04D7, 0x04D9, 0x04DB, 0x04DD,
00380             0x04DF, 0x04E1, 0x04E3, 0x04E5, 0x04E7, 0x04E9, 0x04EB, 0x04ED, 0x04EF, 0x04F1,
00381             0x04F3, 0x04F5, 0x04F9, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
00382             0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, 0x0570, 0x0571,
00383             0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, 0x0578, 0x0579, 0x057A, 0x057B,
00384             0x057C, 0x057D, 0x057E, 0x057F, 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585,
00385             0x0586, 0x1E01, 0x1E03, 0x1E05, 0x1E07, 0x1E09, 0x1E0B, 0x1E0D, 0x1E0F, 0x1E11,
00386             0x1E13, 0x1E15, 0x1E17, 0x1E19, 0x1E1B, 0x1E1D, 0x1E1F, 0x1E21, 0x1E23, 0x1E25,
00387             0x1E27, 0x1E29, 0x1E2B, 0x1E2D, 0x1E2F, 0x1E31, 0x1E33, 0x1E35, 0x1E37, 0x1E39,
00388             0x1E3B, 0x1E3D, 0x1E3F, 0x1E41, 0x1E43, 0x1E45, 0x1E47, 0x1E49, 0x1E4B, 0x1E4D,
00389             0x1E4F, 0x1E51, 0x1E53, 0x1E55, 0x1E57, 0x1E59, 0x1E5B, 0x1E5D, 0x1E5F, 0x1E61,
00390             0x1E63, 0x1E65, 0x1E67, 0x1E69, 0x1E6B, 0x1E6D, 0x1E6F, 0x1E71, 0x1E73, 0x1E75,
00391             0x1E77, 0x1E79, 0x1E7B, 0x1E7D, 0x1E7F, 0x1E81, 0x1E83, 0x1E85, 0x1E87, 0x1E89,
00392             0x1E8B, 0x1E8D, 0x1E8F, 0x1E91, 0x1E93, 0x1E95, 0x1E9B, 0x1EA1, 0x1EA3, 0x1EA5,
00393             0x1EA7, 0x1EA9, 0x1EAB, 0x1EAD, 0x1EAF, 0x1EB1, 0x1EB3, 0x1EB5, 0x1EB7, 0x1EB9,
00394             0x1EBB, 0x1EBD, 0x1EBF, 0x1EC1, 0x1EC3, 0x1EC5, 0x1EC7, 0x1EC9, 0x1ECB, 0x1ECD,
00395             0x1ECF, 0x1ED1, 0x1ED3, 0x1ED5, 0x1ED7, 0x1ED9, 0x1EDB, 0x1EDD, 0x1EDF, 0x1EE1,
00396             0x1EE3, 0x1EE5, 0x1EE7, 0x1EE9, 0x1EEB, 0x1EED, 0x1EEF, 0x1EF1, 0x1EF3, 0x1EF5,
00397             0x1EF7, 0x1EF9, 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
00398             0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F20, 0x1F21, 0x1F22, 0x1F23,
00399             0x1F24, 0x1F25, 0x1F26, 0x1F27, 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35,
00400             0x1F36, 0x1F37, 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F51, 0x1F53,
00401             0x1F55, 0x1F57, 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
00402             0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77, 0x1F78, 0x1F79,
00403             0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85,
00404             0x1F86, 0x1F87, 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
00405             0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7, 0x1FB0, 0x1FB1,
00406             0x1FB3, 0x1FBE, 0x1FC3, 0x1FD0, 0x1FD1, 0x1FE0, 0x1FE1, 0x1FE5, 0x1FF3, 0x2170,
00407             0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A,
00408             0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4,
00409             0x24D5, 0x24D6, 0x24D7, 0x24D8, 0x24D9, 0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE,
00410             0x24DF, 0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, 0x24E7, 0x24E8,
00411             0x24E9, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49,
00412             0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53,
00413             0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A
00414         };
00415 
00416     const wchar String::upperCaseConversion[] = 
00417         {
00418             0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A,
00419             0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054,
00420             0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x039C, 0x00C0, 0x00C1, 0x00C2,
00421             0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC,
00422             0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6,
00423             0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0178, 0x0100, 0x0102,
00424             0x0104, 0x0106, 0x0108, 0x010A, 0x010C, 0x010E, 0x0110, 0x0112, 0x0114, 0x0116,
00425             0x0118, 0x011A, 0x011C, 0x011E, 0x0120, 0x0122, 0x0124, 0x0126, 0x0128, 0x012A,
00426             0x012C, 0x012E, 0x0049, 0x0132, 0x0134, 0x0136, 0x0139, 0x013B, 0x013D, 0x013F,
00427             0x0141, 0x0143, 0x0145, 0x0147, 0x014A, 0x014C, 0x014E, 0x0150, 0x0152, 0x0154,
00428             0x0156, 0x0158, 0x015A, 0x015C, 0x015E, 0x0160, 0x0162, 0x0164, 0x0166, 0x0168,
00429             0x016A, 0x016C, 0x016E, 0x0170, 0x0172, 0x0174, 0x0176, 0x0179, 0x017B, 0x017D,
00430             0x0053, 0x0182, 0x0184, 0x0187, 0x018B, 0x0191, 0x01F6, 0x0198, 0x01A0, 0x01A2,
00431             0x01A4, 0x01A7, 0x01AC, 0x01AF, 0x01B3, 0x01B5, 0x01B8, 0x01BC, 0x01F7, 0x01C4,
00432             0x01C4, 0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CD, 0x01CF, 0x01D1, 0x01D3, 0x01D5,
00433             0x01D7, 0x01D9, 0x01DB, 0x018E, 0x01DE, 0x01E0, 0x01E2, 0x01E4, 0x01E6, 0x01E8,
00434             0x01EA, 0x01EC, 0x01EE, 0x01F1, 0x01F1, 0x01F4, 0x01F8, 0x01FA, 0x01FC, 0x01FE,
00435             0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020A, 0x020C, 0x020E, 0x0210, 0x0212,
00436             0x0214, 0x0216, 0x0218, 0x021A, 0x021C, 0x021E, 0x0222, 0x0224, 0x0226, 0x0228,
00437             0x022A, 0x022C, 0x022E, 0x0230, 0x0232, 0x0181, 0x0186, 0x0189, 0x018A, 0x018F,
00438             0x0190, 0x0193, 0x0194, 0x0197, 0x0196, 0x019C, 0x019D, 0x019F, 0x01A6, 0x01A9,
00439             0x01AE, 0x01B1, 0x01B2, 0x01B7, 0x0399, 0x0386, 0x0388, 0x0389, 0x038A, 0x0391,
00440             0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B,
00441             0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5,
00442             0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0392,
00443             0x0398, 0x03A6, 0x03A0, 0x03DA, 0x03DC, 0x03DE, 0x03E0, 0x03E2, 0x03E4, 0x03E6,
00444             0x03E8, 0x03EA, 0x03EC, 0x03EE, 0x039A, 0x03A1, 0x03A3, 0x0395, 0x0410, 0x0411,
00445             0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B,
00446             0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
00447             0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
00448             0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409,
00449             0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F, 0x0460, 0x0462, 0x0464, 0x0466,
00450             0x0468, 0x046A, 0x046C, 0x046E, 0x0470, 0x0472, 0x0474, 0x0476, 0x0478, 0x047A,
00451             0x047C, 0x047E, 0x0480, 0x048C, 0x048E, 0x0490, 0x0492, 0x0494, 0x0496, 0x0498,
00452             0x049A, 0x049C, 0x049E, 0x04A0, 0x04A2, 0x04A4, 0x04A6, 0x04A8, 0x04AA, 0x04AC,
00453             0x04AE, 0x04B0, 0x04B2, 0x04B4, 0x04B6, 0x04B8, 0x04BA, 0x04BC, 0x04BE, 0x04C1,
00454             0x04C3, 0x04C7, 0x04CB, 0x04D0, 0x04D2, 0x04D4, 0x04D6, 0x04D8, 0x04DA, 0x04DC,
00455             0x04DE, 0x04E0, 0x04E2, 0x04E4, 0x04E6, 0x04E8, 0x04EA, 0x04EC, 0x04EE, 0x04F0,
00456             0x04F2, 0x04F4, 0x04F8, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
00457             0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F, 0x0540, 0x0541,
00458             0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, 0x0548, 0x0549, 0x054A, 0x054B,
00459             0x054C, 0x054D, 0x054E, 0x054F, 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555,
00460             0x0556, 0x1E00, 0x1E02, 0x1E04, 0x1E06, 0x1E08, 0x1E0A, 0x1E0C, 0x1E0E, 0x1E10,
00461             0x1E12, 0x1E14, 0x1E16, 0x1E18, 0x1E1A, 0x1E1C, 0x1E1E, 0x1E20, 0x1E22, 0x1E24,
00462             0x1E26, 0x1E28, 0x1E2A, 0x1E2C, 0x1E2E, 0x1E30, 0x1E32, 0x1E34, 0x1E36, 0x1E38,
00463             0x1E3A, 0x1E3C, 0x1E3E, 0x1E40, 0x1E42, 0x1E44, 0x1E46, 0x1E48, 0x1E4A, 0x1E4C,
00464             0x1E4E, 0x1E50, 0x1E52, 0x1E54, 0x1E56, 0x1E58, 0x1E5A, 0x1E5C, 0x1E5E, 0x1E60,
00465             0x1E62, 0x1E64, 0x1E66, 0x1E68, 0x1E6A, 0x1E6C, 0x1E6E, 0x1E70, 0x1E72, 0x1E74,
00466             0x1E76, 0x1E78, 0x1E7A, 0x1E7C, 0x1E7E, 0x1E80, 0x1E82, 0x1E84, 0x1E86, 0x1E88,
00467             0x1E8A, 0x1E8C, 0x1E8E, 0x1E90, 0x1E92, 0x1E94, 0x1E60, 0x1EA0, 0x1EA2, 0x1EA4,
00468             0x1EA6, 0x1EA8, 0x1EAA, 0x1EAC, 0x1EAE, 0x1EB0, 0x1EB2, 0x1EB4, 0x1EB6, 0x1EB8,
00469             0x1EBA, 0x1EBC, 0x1EBE, 0x1EC0, 0x1EC2, 0x1EC4, 0x1EC6, 0x1EC8, 0x1ECA, 0x1ECC,
00470             0x1ECE, 0x1ED0, 0x1ED2, 0x1ED4, 0x1ED6, 0x1ED8, 0x1EDA, 0x1EDC, 0x1EDE, 0x1EE0,
00471             0x1EE2, 0x1EE4, 0x1EE6, 0x1EE8, 0x1EEA, 0x1EEC, 0x1EEE, 0x1EF0, 0x1EF2, 0x1EF4,
00472             0x1EF6, 0x1EF8, 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
00473             0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F28, 0x1F29, 0x1F2A, 0x1F2B,
00474             0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D,
00475             0x1F3E, 0x1F3F, 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F59, 0x1F5B,
00476             0x1F5D, 0x1F5F, 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
00477             0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, 0x1FF8, 0x1FF9,
00478             0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D,
00479             0x1F8E, 0x1F8F, 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
00480             0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 0x1FB8, 0x1FB9,
00481             0x1FBC, 0x0399, 0x1FCC, 0x1FD8, 0x1FD9, 0x1FE8, 0x1FE9, 0x1FEC, 0x1FFC, 0x2160,
00482             0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A,
00483             0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0x24B6, 0x24B7, 0x24B8, 0x24B9, 0x24BA,
00484             0x24BB, 0x24BC, 0x24BD, 0x24BE, 0x24BF, 0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4,
00485             0x24C5, 0x24C6, 0x24C7, 0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD, 0x24CE,
00486             0x24CF, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29,
00487             0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33,
00488             0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A
00489         };
00490 
00491     // WARNING: This is used by the core flash code. Any change to this utility, or the tables
00492     //          it relies on, will break legacy Flash content.
00493     /*static*/ wchar String::wCharToUpper (wchar ch)
00494     {
00495         AvmAssert (sizeof (lowerCaseBase) == sizeof (upperCaseConversion));
00496 
00497         wchar result = ch;
00498         // Do a binary search in lowerCaseBase for wchar
00499         int lo = 0;
00500         int hi = (sizeof (lowerCaseBase) / sizeof (lowerCaseBase[0])) - 1;
00501 
00502         while (lo <= hi) 
00503         {
00504             int pivot = (lo+hi)>>1;
00505             int testChar = lowerCaseBase[pivot];
00506 
00507             if (ch == testChar) 
00508             {
00509                 // Use that index into lowerCaseConversion for a return value
00510                 result =  upperCaseConversion[pivot];
00511                 break;
00512             } 
00513             else if (ch < testChar) 
00514             {
00515                 hi = pivot-1;
00516             } 
00517             else 
00518             {
00519                 lo = pivot+1;
00520             }
00521         }
00522 
00523         return result;
00524     }
00525 
00526     // 12sep02 grandma : table driven inline function is 14x faster than original function,
00527     // Using first 100 movies of ATS, HashKey alone calls CharToUpper() 360,000 times.
00528 
00529     const unsigned char String::tolower_map[] = {
00530         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //0-15
00531         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //16-31
00532         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //32-47
00533         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //48-64
00534         0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //65-79
00535         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, //80-95
00536         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //96-111
00537         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //112-127
00538         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //128-143
00539         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //144-159
00540         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //160-175
00541         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //176-191
00542         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //192-207
00543         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, //208-224
00544         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //225-239
00545         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  //240-255
00546     };
00547 
00548     const unsigned char String::toupper_map[] = {
00549         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //0-15
00550         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //16-31
00551         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //32-47
00552         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //48-64
00553         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //65-79
00554         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //80-95
00555         0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //96-111
00556         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, //112-127
00557         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //128-143
00558         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //144-159
00559         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //160-175
00560         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //176-191
00561         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //192-207 
00562         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, //208-224
00563         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //225-239
00564         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20  //240-255
00565     };
00566     
00567     const wchar String::upperCaseBase[] = {
00568         0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A,
00569         0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054,
00570         0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00C0, 0x00C1, 0x00C2, 0x00C3,
00571         0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD,
00572         0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D8,
00573         0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0100, 0x0102, 0x0104, 0x0106,
00574         0x0108, 0x010A, 0x010C, 0x010E, 0x0110, 0x0112, 0x0114, 0x0116, 0x0118, 0x011A,
00575         0x011C, 0x011E, 0x0120, 0x0122, 0x0124, 0x0126, 0x0128, 0x012A, 0x012C, 0x012E,
00576         0x0130, 0x0132, 0x0134, 0x0136, 0x0139, 0x013B, 0x013D, 0x013F, 0x0141, 0x0143,
00577         0x0145, 0x0147, 0x014A, 0x014C, 0x014E, 0x0150, 0x0152, 0x0154, 0x0156, 0x0158,
00578         0x015A, 0x015C, 0x015E, 0x0160, 0x0162, 0x0164, 0x0166, 0x0168, 0x016A, 0x016C,
00579         0x016E, 0x0170, 0x0172, 0x0174, 0x0176, 0x0178, 0x0179, 0x017B, 0x017D, 0x0181,
00580         0x0182, 0x0184, 0x0186, 0x0187, 0x0189, 0x018A, 0x018B, 0x018E, 0x018F, 0x0190,
00581         0x0191, 0x0193, 0x0194, 0x0196, 0x0197, 0x0198, 0x019C, 0x019D, 0x019F, 0x01A0,
00582         0x01A2, 0x01A4, 0x01A6, 0x01A7, 0x01A9, 0x01AC, 0x01AE, 0x01AF, 0x01B1, 0x01B2,
00583         0x01B3, 0x01B5, 0x01B7, 0x01B8, 0x01BC, 0x01C4, 0x01C5, 0x01C7, 0x01C8, 0x01CA,
00584         0x01CB, 0x01CD, 0x01CF, 0x01D1, 0x01D3, 0x01D5, 0x01D7, 0x01D9, 0x01DB, 0x01DE,
00585         0x01E0, 0x01E2, 0x01E4, 0x01E6, 0x01E8, 0x01EA, 0x01EC, 0x01EE, 0x01F1, 0x01F2,
00586         0x01F4, 0x01F6, 0x01F7, 0x01F8, 0x01FA, 0x01FC, 0x01FE, 0x0200, 0x0202, 0x0204,
00587         0x0206, 0x0208, 0x020A, 0x020C, 0x020E, 0x0210, 0x0212, 0x0214, 0x0216, 0x0218,
00588         0x021A, 0x021C, 0x021E, 0x0222, 0x0224, 0x0226, 0x0228, 0x022A, 0x022C, 0x022E,
00589         0x0230, 0x0232, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, 0x038F, 0x0391,
00590         0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B,
00591         0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6,
00592         0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03DA, 0x03DC, 0x03DE, 0x03E0, 0x03E2,
00593         0x03E4, 0x03E6, 0x03E8, 0x03EA, 0x03EC, 0x03EE, 0x03F4, 0x0400, 0x0401, 0x0402,
00594         0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C,
00595         0x040D, 0x040E, 0x040F, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416,
00596         0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420,
00597         0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A,
00598         0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0460, 0x0462, 0x0464, 0x0466, 0x0468,
00599         0x046A, 0x046C, 0x046E, 0x0470, 0x0472, 0x0474, 0x0476, 0x0478, 0x047A, 0x047C,
00600         0x047E, 0x0480, 0x048C, 0x048E, 0x0490, 0x0492, 0x0494, 0x0496, 0x0498, 0x049A,
00601         0x049C, 0x049E, 0x04A0, 0x04A2, 0x04A4, 0x04A6, 0x04A8, 0x04AA, 0x04AC, 0x04AE,
00602         0x04B0, 0x04B2, 0x04B4, 0x04B6, 0x04B8, 0x04BA, 0x04BC, 0x04BE, 0x04C1, 0x04C3,
00603         0x04C7, 0x04CB, 0x04D0, 0x04D2, 0x04D4, 0x04D6, 0x04D8, 0x04DA, 0x04DC, 0x04DE,
00604         0x04E0, 0x04E2, 0x04E4, 0x04E6, 0x04E8, 0x04EA, 0x04EC, 0x04EE, 0x04F0, 0x04F2,
00605         0x04F4, 0x04F8, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, 0x0538,
00606         0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F, 0x0540, 0x0541, 0x0542,
00607         0x0543, 0x0544, 0x0545, 0x0546, 0x0547, 0x0548, 0x0549, 0x054A, 0x054B, 0x054C,
00608         0x054D, 0x054E, 0x054F, 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556,
00609         // cn: added Georgian.  Not in the UnicodeData-3.2.0 spreadsheet, but was added later
00610         0x10a0, 0x10a1, 0x10a2, 0x10a3, 0x10a4, 0x10a5, 0x10a6, 0x10a7, 0x10a8, 0x10a9, 
00611         0x10aa, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af, 0x10b0, 0x10b1, 0x10b2, 0x10b3, 
00612         0x10b4, 0x10b5, 0x10b6, 0x10b7, 0x10b8, 0x10b9, 0x10ba, 0x10bb, 0x10bc, 0x10bd, 
00613         0x10be, 0x10bf, 0x10c0, 0x10c1, 0x10c2, 0x10c3, 0x10c4, 0x10c5, 
00614         // cn: end Georgian.
00615         0x1E00, 0x1E02, 0x1E04, 0x1E06, 0x1E08, 0x1E0A, 0x1E0C, 0x1E0E, 0x1E10, 0x1E12,
00616         0x1E14, 0x1E16, 0x1E18, 0x1E1A, 0x1E1C, 0x1E1E, 0x1E20, 0x1E22, 0x1E24, 0x1E26,
00617         0x1E28, 0x1E2A, 0x1E2C, 0x1E2E, 0x1E30, 0x1E32, 0x1E34, 0x1E36, 0x1E38, 0x1E3A,
00618         0x1E3C, 0x1E3E, 0x1E40, 0x1E42, 0x1E44, 0x1E46, 0x1E48, 0x1E4A, 0x1E4C, 0x1E4E,
00619         0x1E50, 0x1E52, 0x1E54, 0x1E56, 0x1E58, 0x1E5A, 0x1E5C, 0x1E5E, 0x1E60, 0x1E62,
00620         0x1E64, 0x1E66, 0x1E68, 0x1E6A, 0x1E6C, 0x1E6E, 0x1E70, 0x1E72, 0x1E74, 0x1E76,
00621         0x1E78, 0x1E7A, 0x1E7C, 0x1E7E, 0x1E80, 0x1E82, 0x1E84, 0x1E86, 0x1E88, 0x1E8A,
00622         0x1E8C, 0x1E8E, 0x1E90, 0x1E92, 0x1E94, 0x1EA0, 0x1EA2, 0x1EA4, 0x1EA6, 0x1EA8,
00623         0x1EAA, 0x1EAC, 0x1EAE, 0x1EB0, 0x1EB2, 0x1EB4, 0x1EB6, 0x1EB8, 0x1EBA, 0x1EBC,
00624         0x1EBE, 0x1EC0, 0x1EC2, 0x1EC4, 0x1EC6, 0x1EC8, 0x1ECA, 0x1ECC, 0x1ECE, 0x1ED0,
00625         0x1ED2, 0x1ED4, 0x1ED6, 0x1ED8, 0x1EDA, 0x1EDC, 0x1EDE, 0x1EE0, 0x1EE2, 0x1EE4,
00626         0x1EE6, 0x1EE8, 0x1EEA, 0x1EEC, 0x1EEE, 0x1EF0, 0x1EF2, 0x1EF4, 0x1EF6, 0x1EF8,
00627         0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 0x1F18, 0x1F19,
00628         0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D,
00629         0x1F2E, 0x1F2F, 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
00630         0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F59, 0x1F5B, 0x1F5D, 0x1F5F,
00631         0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 0x1F88, 0x1F89,
00632         0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 0x1F98, 0x1F99, 0x1F9A, 0x1F9B,
00633         0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD,
00634         0x1FAE, 0x1FAF, 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FC8, 0x1FC9, 0x1FCA,
00635         0x1FCB, 0x1FCC, 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB,
00636         0x1FEC, 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x2126, 0x212A, 0x212B, 0x2160,
00637         0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A,
00638         0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0x24B6, 0x24B7, 0x24B8, 0x24B9, 0x24BA,
00639         0x24BB, 0x24BC, 0x24BD, 0x24BE, 0x24BF, 0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4,
00640         0x24C5, 0x24C6, 0x24C7, 0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD, 0x24CE,
00641         0x24CF, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29,
00642         0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33,
00643         0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A
00644     };
00645 
00646     const wchar String::lowerCaseConversion[] = {
00647         0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
00648         0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
00649         0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x00E0, 0x00E1, 0x00E2, 0x00E3,
00650         0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED,
00651         0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F8,
00652         0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0101, 0x0103, 0x0105, 0x0107,
00653         0x0109, 0x010B, 0x010D, 0x010F, 0x0111, 0x0113, 0x0115, 0x0117, 0x0119, 0x011B,
00654         0x011D, 0x011F, 0x0121, 0x0123, 0x0125, 0x0127, 0x0129, 0x012B, 0x012D, 0x012F,
00655         0x0069, 0x0133, 0x0135, 0x0137, 0x013A, 0x013C, 0x013E, 0x0140, 0x0142, 0x0144,
00656         0x0146, 0x0148, 0x014B, 0x014D, 0x014F, 0x0151, 0x0153, 0x0155, 0x0157, 0x0159,
00657         0x015B, 0x015D, 0x015F, 0x0161, 0x0163, 0x0165, 0x0167, 0x0169, 0x016B, 0x016D,
00658         0x016F, 0x0171, 0x0173, 0x0175, 0x0177, 0x00FF, 0x017A, 0x017C, 0x017E, 0x0253,
00659         0x0183, 0x0185, 0x0254, 0x0188, 0x0256, 0x0257, 0x018C, 0x01DD, 0x0259, 0x025B,
00660         0x0192, 0x0260, 0x0263, 0x0269, 0x0268, 0x0199, 0x026F, 0x0272, 0x0275, 0x01A1,
00661         0x01A3, 0x01A5, 0x0280, 0x01A8, 0x0283, 0x01AD, 0x0288, 0x01B0, 0x028A, 0x028B,
00662         0x01B4, 0x01B6, 0x0292, 0x01B9, 0x01BD, 0x01C6, 0x01C6, 0x01C9, 0x01C9, 0x01CC,
00663         0x01CC, 0x01CE, 0x01D0, 0x01D2, 0x01D4, 0x01D6, 0x01D8, 0x01DA, 0x01DC, 0x01DF,
00664         0x01E1, 0x01E3, 0x01E5, 0x01E7, 0x01E9, 0x01EB, 0x01ED, 0x01EF, 0x01F3, 0x01F3,
00665         0x01F5, 0x0195, 0x01BF, 0x01F9, 0x01FB, 0x01FD, 0x01FF, 0x0201, 0x0203, 0x0205,
00666         0x0207, 0x0209, 0x020B, 0x020D, 0x020F, 0x0211, 0x0213, 0x0215, 0x0217, 0x0219,
00667         0x021B, 0x021D, 0x021F, 0x0223, 0x0225, 0x0227, 0x0229, 0x022B, 0x022D, 0x022F,
00668         0x0231, 0x0233, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03CC, 0x03CD, 0x03CE, 0x03B1,
00669         0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB,
00670         0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6,
00671         0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03DB, 0x03DD, 0x03DF, 0x03E1, 0x03E3,
00672         0x03E5, 0x03E7, 0x03E9, 0x03EB, 0x03ED, 0x03EF, 0x03B8, 0x0450, 0x0451, 0x0452,
00673         0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C,
00674         0x045D, 0x045E, 0x045F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436,
00675         0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440,
00676         0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A,
00677         0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 0x0461, 0x0463, 0x0465, 0x0467, 0x0469,
00678         0x046B, 0x046D, 0x046F, 0x0471, 0x0473, 0x0475, 0x0477, 0x0479, 0x047B, 0x047D,
00679         0x047F, 0x0481, 0x048D, 0x048F, 0x0491, 0x0493, 0x0495, 0x0497, 0x0499, 0x049B,
00680         0x049D, 0x049F, 0x04A1, 0x04A3, 0x04A5, 0x04A7, 0x04A9, 0x04AB, 0x04AD, 0x04AF,
00681         0x04B1, 0x04B3, 0x04B5, 0x04B7, 0x04B9, 0x04BB, 0x04BD, 0x04BF, 0x04C2, 0x04C4,
00682         0x04C8, 0x04CC, 0x04D1, 0x04D3, 0x04D5, 0x04D7, 0x04D9, 0x04DB, 0x04DD, 0x04DF,
00683         0x04E1, 0x04E3, 0x04E5, 0x04E7, 0x04E9, 0x04EB, 0x04ED, 0x04EF, 0x04F1, 0x04F3,
00684         0x04F5, 0x04F9, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, 0x0568,
00685         0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, 0x0570, 0x0571, 0x0572,
00686         0x0573, 0x0574, 0x0575, 0x0576, 0x0577, 0x0578, 0x0579, 0x057A, 0x057B, 0x057C,
00687         0x057D, 0x057E, 0x057F, 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586,
00688         // cn: added Georgian.  Not in the UnicodeData-3.2.0 spreadsheet, but was added later
00689         0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, 0x10d8, 0x10d9, 
00690         0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, 0x10e0, 0x10e1, 0x10e2, 0x10e3, 
00691         0x10e4, 0x10e5, 0x10e6, 0x10e7, 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 
00692         0x10ee, 0x10ef, 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 
00693         // cn: end Georgian.
00694         0x1E01, 0x1E03, 0x1E05, 0x1E07, 0x1E09, 0x1E0B, 0x1E0D, 0x1E0F, 0x1E11, 0x1E13,
00695         0x1E15, 0x1E17, 0x1E19, 0x1E1B, 0x1E1D, 0x1E1F, 0x1E21, 0x1E23, 0x1E25, 0x1E27,
00696         0x1E29, 0x1E2B, 0x1E2D, 0x1E2F, 0x1E31, 0x1E33, 0x1E35, 0x1E37, 0x1E39, 0x1E3B,
00697         0x1E3D, 0x1E3F, 0x1E41, 0x1E43, 0x1E45, 0x1E47, 0x1E49, 0x1E4B, 0x1E4D, 0x1E4F,
00698         0x1E51, 0x1E53, 0x1E55, 0x1E57, 0x1E59, 0x1E5B, 0x1E5D, 0x1E5F, 0x1E61, 0x1E63,
00699         0x1E65, 0x1E67, 0x1E69, 0x1E6B, 0x1E6D, 0x1E6F, 0x1E71, 0x1E73, 0x1E75, 0x1E77,
00700         0x1E79, 0x1E7B, 0x1E7D, 0x1E7F, 0x1E81, 0x1E83, 0x1E85, 0x1E87, 0x1E89, 0x1E8B,
00701         0x1E8D, 0x1E8F, 0x1E91, 0x1E93, 0x1E95, 0x1EA1, 0x1EA3, 0x1EA5, 0x1EA7, 0x1EA9,
00702         0x1EAB, 0x1EAD, 0x1EAF, 0x1EB1, 0x1EB3, 0x1EB5, 0x1EB7, 0x1EB9, 0x1EBB, 0x1EBD,
00703         0x1EBF, 0x1EC1, 0x1EC3, 0x1EC5, 0x1EC7, 0x1EC9, 0x1ECB, 0x1ECD, 0x1ECF, 0x1ED1,
00704         0x1ED3, 0x1ED5, 0x1ED7, 0x1ED9, 0x1EDB, 0x1EDD, 0x1EDF, 0x1EE1, 0x1EE3, 0x1EE5,
00705         0x1EE7, 0x1EE9, 0x1EEB, 0x1EED, 0x1EEF, 0x1EF1, 0x1EF3, 0x1EF5, 0x1EF7, 0x1EF9,
00706         0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07, 0x1F10, 0x1F11,
00707         0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25,
00708         0x1F26, 0x1F27, 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
00709         0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F51, 0x1F53, 0x1F55, 0x1F57,
00710         0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, 0x1F80, 0x1F81,
00711         0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87, 0x1F90, 0x1F91, 0x1F92, 0x1F93,
00712         0x1F94, 0x1F95, 0x1F96, 0x1F97, 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5,
00713         0x1FA6, 0x1FA7, 0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1F72, 0x1F73, 0x1F74,
00714         0x1F75, 0x1FC3, 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B,
00715         0x1FE5, 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x03C9, 0x006B, 0x00E5, 0x2170,
00716         0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A,
00717         0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4,
00718         0x24D5, 0x24D6, 0x24D7, 0x24D8, 0x24D9, 0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE,
00719         0x24DF, 0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, 0x24E7, 0x24E8,
00720         0x24E9, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49,
00721         0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53,
00722         0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A
00723     };
00724 
00725     // WARNING: This is used by the core flash code. Any change to this utility, or the tables
00726     //          it relies on, will break legacy Flash content.
00727     /*static*/ wchar String::wCharToLower(wchar ch)
00728     {
00729         AvmAssert (sizeof (upperCaseBase) == sizeof (lowerCaseConversion));
00730 
00731         wchar result = ch;
00732         // Do a binary search in upperCaseBase for wchar
00733         int lo = 0;
00734         int hi = (sizeof (upperCaseBase) / sizeof (upperCaseBase[0])) - 1;
00735 
00736         while (lo <= hi) 
00737         {
00738             int pivot = (lo+hi)>>1;
00739             int testChar = upperCaseBase[pivot];
00740 
00741             if (ch == testChar) 
00742             {
00743                 // Use that index into lowerCaseConversion for a return value
00744                 result =  lowerCaseConversion[pivot];
00745                 break;
00746             } 
00747             else if (ch < testChar) 
00748             {
00749                 hi = pivot-1;
00750             } 
00751             else 
00752             {
00753                 lo = pivot+1;
00754             }
00755         }
00756 
00757         return result;
00758     }
00759 
00760     Stringp String::toUpperCase()
00761     {
00762         GC* gc = GC::GetGC(this);
00763         int len = length();
00764         Stringp out = new (gc) String(len);
00765 
00766         // Flag to detect whether any changes were made
00767         bool changed = false;
00768 
00769         // First, try quick conversion for low ASCII characters.
00770         wchar *dst = out->lockBuffer();
00771         const wchar *src = c_str();
00772         const wchar *end = src + len;
00773         wchar charIn, charOut;
00774         while (src < end) 
00775         {
00776             charIn = *src;
00777             if (charIn >= 0xFF)
00778                 break;
00779 
00780             charOut = String::toupper_map[charIn] ^ charIn;
00781             if (charOut != charIn) 
00782                 changed = true;
00783 
00784             *dst++ = charOut;
00785             src++;
00786         }
00787 
00788         // If that didn't work, resume from where we left off
00789         // with slow full Unicode conversion.
00790         while (src < end) 
00791         {
00792             charIn = *src;
00793             charOut = wCharToUpper(charIn);
00794             if (charOut != charIn)
00795                 changed = true;
00796 
00797             *dst++ = charOut;
00798             src++;  
00799         }
00800         
00801         *dst = 0;
00802         out->unlockBuffer();
00803 
00804         // Return new string.  If nothing changed, return old
00805         // string (the new string will be GC'd)
00806         return changed ? out : this;
00807     }
00808 
00809     Stringp String::toLowerCase() 
00810     {
00811         GC* gc = GC::GetGC(this);
00812         int len = length();
00813         Stringp out = new (gc) String(len);
00814 
00815         // Flag to detect whether any changes were made
00816         bool changed = false;
00817 
00818         // First, try quick conversion for low ASCII characters.
00819         wchar *dst = out->lockBuffer();
00820         const wchar *src = c_str();
00821         const wchar *end = src + len;
00822         wchar charIn, charOut;
00823         while (src < end) 
00824         {
00825             charIn = *src;
00826             if (charIn >= 0xFF)
00827                 break;
00828 
00829             charOut = String::tolower_map[charIn] ^ charIn;
00830             if (charOut != charIn)
00831                 changed = true;
00832 
00833             *dst++ = charOut;
00834             src++;
00835         }
00836 
00837         // If that didn't work, resume from where we left off
00838         // with slow full Unicode conversion.
00839         while (src < end) 
00840         {
00841             charIn = *src;
00842             charOut = wCharToLower(charIn);
00843             if (charOut != charIn)
00844                 changed = true;
00845 
00846             *dst++ = charOut;
00847             src++;
00848         }
00849         
00850         *dst = 0;
00851         out->unlockBuffer();
00852 
00853         // Return new string.  If nothing changed, return old
00854         // string (the new string will be GC'd)
00855         return changed ? out : this;
00856     }
00857 
00858     int String::indexOf(Stringp substr, int iStartPos)
00859     {
00860         if(!substr)
00861             return -1;
00862 
00863         int sublen = substr->length();
00864         if (iStartPos > this->length()) 
00865             iStartPos = this->length();
00866 
00867         // iRight is the last character in selfString subStr could be found at
00868         // (and further, and there isn't enough of selfString remaining for a match to be possible)
00869         const int iRight = this->length() - sublen; 
00870         
00871         // bug 78346: argv[1] might be less than zero.
00872         // We clamp it to zero for two reasons:
00873         //  1. A movie created prior to this fix with a small negative value probably worked,
00874         //  so let's fix it without breaking them.
00875         //  2. I am told this is what java does.
00876         //
00877         // if (argv[1] > iRight), then we never enter the loop
00878         if (iStartPos < 0) {
00879             iStartPos = 0;
00880         }
00881 
00882         // our substr to find is only one character
00883         if (sublen == 1) 
00884         {
00885             const wchar substrchar = substr->c_str()[0];
00886             const wchar *selfstr = this->c_str();
00887             for ( ; iStartPos <= iRight; iStartPos++)
00888             {
00889                 if (substrchar == selfstr[iStartPos])
00890                 {
00891                     return iStartPos;
00892                 }
00893             }
00894         }
00895         else
00896         {
00897             const wchar *substrstr = substr->c_str();
00898             const wchar *selfstr = this->c_str();
00899             selfstr += iStartPos;
00900             for ( ; iStartPos <= iRight; iStartPos++)
00901             {
00902                 int j;
00903                 for (j = 0; j < sublen; j++)
00904                 {
00905                     if (substrstr[j] != selfstr[j])
00906                     {
00907                         break;
00908                     }
00909                 }
00910 
00911                 if (j == sublen)
00912                 {
00913                     return iStartPos;
00914                 }
00915                 selfstr++;
00916             }
00917         }
00918 
00919         return -1;
00920     }
00921 
00922     int String::indexOfDouble(Stringp substr, double dStartPos)
00923     {
00924         dStartPos = MathUtils::toInt(dStartPos);
00925         int iStartPos = (dStartPos > (double)this->length() ? this->length() : (int)dStartPos);
00926         return indexOf (substr, iStartPos);
00927     }
00928 
00929     Stringp String::charAt(int iPos)
00930     {
00931         GC *gc = GC::GetGC(this);
00932         AvmCore *core = (AvmCore *) gc->GetGCContextVariable (MMgc::GC::GCV_AVMCORE);
00933         if (iPos >= 0 && iPos < length()) 
00934         {
00935             wchar ch = !this->needsNormalization() ? getData()[iPos] : ((*this)[iPos]);
00936             if (ch < 128)
00937             {
00938                 return core->cachedChars[ch];
00939             }
00940             else
00941             {
00942                 return new (gc) String(this, iPos, 1);
00943             }
00944         }
00945         else
00946         {
00947             return core->kEmptyString;
00948         }
00949     }
00950 
00951     Stringp String::charAtDouble(double dPos)
00952     {
00953         dPos = MathUtils::toInt(dPos);
00954         int iPos = (dPos > (double)this->length()) ? this->length() : (int)dPos;
00955         return charAt (iPos);
00956     }
00957 
00958     double String::charCodeAt(int iPos)
00959     {
00960         if (iPos >= 0 && iPos < length())
00961             return (*this)[iPos];
00962         else
00963             return MathUtils::nan();
00964     }
00965 
00966     double String::charCodeAtDouble(double dPos)
00967     {
00968         dPos = MathUtils::toInt(dPos);
00969         int iPos = (dPos > (double)this->length()) ? this->length() : (int)dPos;
00970         return charCodeAt (iPos);
00971     }
00972 
00973     const wchar* String::c_str() 
00974     {
00975         // For offset too since our string needs to be null terminated
00976         if (needsNormalization()) normalize();
00977         return getData(); 
00978     }
00979 
00980     wchar String::operator[] (int index)
00981     {
00982         AvmAssert(index >=0 && index < length());
00983         if (!hasPrefix())
00984         {
00985             return getData()[index + getOffset()];
00986         }
00987         else
00988         {
00989             AvmAssert (hasPrefix());
00990             normalize();
00991             return getData()[index];
00992 
00993 #if 0 // This is the code if we want to skip the normalizations
00994             // if this is a composite string, find the prefix containing iPos
00995             Stringp s = this;
00996             while (s->getPrefix() && index < s->getPrefix()->length())
00997                 s = s->getPrefix();
00998 
00999             if (s->getPrefix())
01000                 index -= s->getPrefix()->length();
01001             return s->getData()[s->getOffset() + index];
01002 #endif
01003         }
01004     }
01005 
01006     wchar* String::lockBuffer() 
01007     {
01008         // For offset too since our string needs to be null terminated
01009         if (needsNormalization()) normalize();
01010         return (wchar*) getData(); 
01011     }
01012 
01013     /*static*/ bool String::isSpace(wchar ch)
01014     {
01015         return (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
01016     }
01017 
01018     bool String::isWhitespace()
01019     {
01020         Stringp s = this;
01021         do
01022         {
01023             int base = !s->getPrefix() ? 0 : s->getPrefix()->length();
01024             for (int i = s->length()-base-1; i >= 0; i--)
01025                 if (!isSpace(s->getData()[s->getOffset() + i]))
01026                     return false;
01027         }
01028         while ( (s = s->getPrefix()) != 0);
01029         return true;
01030     }
01031 
01032     int String::lastIndexOf(Stringp substr, int iStartPos)
01033     {
01034         int sublen = substr->length();
01035         iStartPos = (iStartPos > this->length()) ? this->length() : iStartPos;
01036 
01037         // iRight is the last character in selfString subStr could be found at
01038         // (and further, and there isn't enough of selfString remaining for a match to be possible)
01039         const int iRight = this->length() - sublen; 
01040         
01041         // bug 78346: argv[1] might be greater than iRight
01042         //  (similar reasons to above apply).
01043         if (iStartPos > iRight) {
01044             iStartPos = iRight;
01045         }
01046 
01047         if (sublen == 0)
01048             return iStartPos;
01049 
01050         const wchar *substrstr = substr->c_str();
01051         const wchar *selfstr = this->c_str() + iStartPos;
01052         for ( ; iStartPos >= 0 ; iStartPos-- )
01053         {
01054             for (int j = 0; j < sublen; j++)
01055             {
01056                 if (substrstr[j] != selfstr[j])
01057                 {
01058                     break;
01059                 }
01060 
01061                 if (j == (sublen - 1))
01062                     return iStartPos;
01063             }
01064 
01065             selfstr--;
01066         }
01067 
01068         return -1;
01069     }
01070 
01071     int String::lastIndexOfDouble(Stringp substr, double dStartPos)
01072     {
01073         if (!MathUtils::isNaN(dStartPos))
01074             dStartPos = MathUtils::toInt(dStartPos);
01075         else
01076             dStartPos = this->length();
01077         int iStartPos = (dStartPos > this->length() ? this->length() : (int)dStartPos);
01078         return lastIndexOf (substr, iStartPos);
01079     }
01080 
01081     int String::localeCompare(Stringp other)
01082     {  
01083         if ( !other )
01084         {
01085             GC *gc = GC::GetGC(this);
01086             AvmCore *core = (AvmCore *) gc->GetGCContextVariable (MMgc::GC::GCV_AVMCORE);
01087             other = core->knull;
01088         }
01089 
01090         return other->Compare(*this);
01091     }
01092 
01093     void String::generateIntegerEquivalent (AvmCore* core)
01094     {
01095         AvmAssert(this->isInterned());
01096         AvmAssert(!this->hasOffset());
01097         AvmAssert(!this->hasPrefix());
01098         uint32 index;
01099         (void)core;
01100         if (core->getIndexFromString (this, &index))
01101         {
01102             if (!(index & ScriptObject::MAX_INTEGER_MASK))
01103             {
01104                 m_prefixOrOffsetOrNumber = index<<3 | NUMBERFLAG;
01105             }
01106         }
01107     }
01108         
01109     String::StringBuf *String::allocBuf(int numChars)
01110     {
01111         GC* gc = GC::GetGC(this);
01112         return new (gc, sizeof(wchar)*(numChars+1)) StringBuf();
01113     }
01114 
01115     Stringp String::substring(int start, int end)
01116     {
01117         GC *gc = GC::GetGC(this);
01118         NativeObjectHelpers::ClampBInt(start, end, this->length());
01119         return new (gc) String(this, start, (end-start));
01120     }
01121 
01122     Stringp String::substringDouble(double d_start, double d_end)
01123     {
01124         GC *gc = GC::GetGC(this);
01125         double start = MathUtils::toInt(d_start);
01126         double end = MathUtils::toInt(d_end);
01127         NativeObjectHelpers::ClampB(start, end, length());
01128         return new (gc) String(this, (int)start, (int)(end-start));
01129     }
01130 
01131     Stringp String::slice(int start, int end)
01132     {
01133         GC *gc = GC::GetGC(this);
01134         int len = this->length();
01135         start = (int)NativeObjectHelpers::ClampIndexInt(start, len); 
01136         end = (int)NativeObjectHelpers::ClampIndexInt(end, len); 
01137         if (end < start)
01138             end = start;
01139 
01140         return new (gc) String(this, start, end-start);
01141     }
01142 
01143     Stringp String::sliceDouble(double d_start, double d_end)
01144     {
01145         GC *gc = GC::GetGC(this);
01146         int len = this->length();
01147         int start = (int)NativeObjectHelpers::ClampIndex(MathUtils::toInt(d_start), len); 
01148         int end = (int)NativeObjectHelpers::ClampIndex(MathUtils::toInt(d_end), len); 
01149         if (end < start)
01150             end = start;
01151 
01152         return new (gc) String(this, start, end-start);
01153     }
01154 
01155     Stringp String::substr(int start, int end)
01156     {
01157         GC *gc = GC::GetGC(this);
01158         int len = this->length();
01159         start = (int)NativeObjectHelpers::ClampIndexInt(start, len); 
01160         // ClampIndex takes a double (not int or uint) for first parm...
01161         // we must cast these to double before addition, otherwise we
01162         // can have numeric overflow with the default arg (end=0x7fffffff)
01163         // and wrap to negative, which would be bad...
01164 
01165         // Do some sanity checks on our ints to see if they will fall within a valid integer range
01166         // !!@what about negative values?
01167         if (end == 0x7ffffff)           
01168         {
01169             end = len; 
01170         }
01171         else if ((end > 0xffffff) || (start > 0xffffff)) // might overflow - use doubles
01172         {
01173             end = (int)NativeObjectHelpers::ClampIndex(double(end) + double(start), len); 
01174         }
01175         else
01176         {
01177             end = (int)NativeObjectHelpers::ClampIndexInt(end + start, len); 
01178         }
01179 
01180         if (end < start)
01181             end = start;
01182 
01183         return new (gc) String(this, start, end-start);
01184     }
01185 
01186     Stringp String::substrDouble(double d_start, double d_end)
01187     {
01188         GC *gc = GC::GetGC(this);
01189         int len = this->length();
01190         int start = (int)NativeObjectHelpers::ClampIndex(MathUtils::toInt(d_start), len); 
01191         // ClampIndex takes a double (not int or uint) for first parm...
01192         // we must cast these to double before addition, otherwise we
01193         // can have numeric overflow with the default arg (end=0x7fffffff)
01194         // and wrap to negative, which would be bad...
01195         int end = (int)NativeObjectHelpers::ClampIndex(MathUtils::toInt(d_end) + (double)start, len); 
01196         if (end < start)
01197             end = start;
01198 
01199         return new (gc) String(this, start, end-start);
01200     }
01201 
01202      void String::setPrefixOrOffsetOrNumber(uintptr value)
01203      {
01204 #ifdef MMGC_DRC
01205          // first decrement existing prefix
01206          if((m_prefixOrOffsetOrNumber & STRINGFLAGS) == PREFIXFLAG)
01207             getPrefix()->DecrementRef();
01208 #endif
01209          GC::GetGC(this)->WriteBarrierNoSubstitute(this, (void*)value);
01210          m_prefixOrOffsetOrNumber = value;
01211 #ifdef MMGC_DRC
01212          if((value & STRINGFLAGS) == PREFIXFLAG)
01213              getPrefix()->IncrementRef();
01214 #endif
01215      }
01216 
01217 #ifdef DEBUGGER
01218     uint64 String::size() const
01219     {
01220         uint64 size = sizeof(String) - sizeof(AvmPlusScriptableObject);
01221         uint64 bufSize = sizeof(StringBuf) + length() * sizeof(wchar);
01222         if(m_buf->RefCount() != 0)
01223             size += bufSize / m_buf->RefCount();
01224         else
01225             size += bufSize;
01226         return size;
01227     }
01228 #endif
01229 
01230     StringNullTerminatedUTF8::StringNullTerminatedUTF8(MMgc::GC *gc, Stringp str) :
01231         m_str(str),
01232         m_bufptr(NULL),
01233         gc(gc)
01234     {
01235         MMGC_MEM_TYPE("StringNullTerminatedUTF8");
01236         int len = str->length();
01237         m_bufptr = (char*)gc->Alloc(len + 1);
01238        const wchar *data = str->c_str();
01239         for (int i=0; i < len; i++) {
01240             m_bufptr[i] = (char) data[i];
01241         }
01242         m_bufptr[len] = 0;
01243     }
01244 
01245     StringNullTerminatedUTF8::~StringNullTerminatedUTF8()
01246     {
01247         gc->Free(m_bufptr);
01248         m_str = NULL;
01249         m_bufptr = NULL;
01250     }
01251 }   

Generated on Sun Oct 12 18:50:02 2008 for Tamarin by  doxygen 1.4.6