Home | History | Annotate | Download | only in String
      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* ***** BEGIN LICENSE BLOCK *****
      3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
      4  *
      5  * The contents of this file are subject to the Mozilla Public License Version
      6  * 1.1 (the "License"); you may not use this file except in compliance with
      7  * the License. You may obtain a copy of the License at
      8  * http://www.mozilla.org/MPL/
      9  *
     10  * Software distributed under the License is distributed on an "AS IS" basis,
     11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
     12  * for the specific language governing rights and limitations under the
     13  * License.
     14  *
     15  * The Original Code is Mozilla Communicator client code, released
     16  * March 31, 1998.
     17  *
     18  * The Initial Developer of the Original Code is
     19  * Netscape Communications Corporation.
     20  * Portions created by the Initial Developer are Copyright (C) 1998
     21  * the Initial Developer. All Rights Reserved.
     22  *
     23  * Contributor(s):
     24  *
     25  * Alternatively, the contents of this file may be used under the terms of
     26  * either the GNU General Public License Version 2 or later (the "GPL"), or
     27  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
     28  * in which case the provisions of the GPL or the LGPL are applicable instead
     29  * of those above. If you wish to allow use of your version of this file only
     30  * under the terms of either the GPL or the LGPL, and not to allow others to
     31  * use your version of this file under the terms of the MPL, indicate your
     32  * decision by deleting the provisions above and replace them with the notice
     33  * and other provisions required by the GPL or the LGPL. If you do not delete
     34  * the provisions above, a recipient may use your version of this file under
     35  * the terms of any one of the MPL, the GPL or the LGPL.
     36  *
     37  * ***** END LICENSE BLOCK ***** */
     38 /**
     39    File Name:          15.5.4.11-2.js
     40    ECMA Section:       15.5.4.11 String.prototype.toLowerCase()
     41    Description:
     42 
     43    Returns a string equal in length to the length of the result of converting
     44    this object to a string. The result is a string value, not a String object.
     45 
     46    Every character of the result is equal to the corresponding character of the
     47    string, unless that character has a Unicode 2.0 uppercase equivalent, in which
     48    case the uppercase equivalent is used instead. (The canonical Unicode 2.0 case
     49    mapping shall be used, which does not depend on implementation or locale.)
     50 
     51    Note that the toLowerCase function is intentionally generic; it does not require
     52    that its this value be a String object. Therefore it can be transferred to other
     53    kinds of objects for use as a method.
     54 
     55    Author:             christine (at) netscape.com
     56    Date:               12 november 1997
     57 */
     58 /*
     59     Safari Changes:  This test differs from the mozilla tests in two significant
     60     ways.
     61         First, the lower case range for Georgian letters in this file is the
     62     correct range according to the Unicode 5.0 standard, as opposed to the
     63     Georgian caseless range that mozilla uses.
     64         Secondly this test uses an array for expected results with two entries,
     65     instead of a single expected result. This allows us to accept Unicode 4.0 or
     66     Unicode 5.0 results as correct, as opposed to the mozilla test, which assumes
     67     Unicode 5.0.  This allows Safari to pass this test on OS' with different
     68     Unicode standards implemented (e.g. Tiger and XP)
     69 */
     70     var SECTION = "15.5.4.11-2";
     71     var VERSION = "ECMA_1";
     72     startTest();
     73     var TITLE   = "String.prototype.toLowerCase()";
     74 
     75     writeHeaderToLog( SECTION + " "+ TITLE);
     76 
     77     var testcases = getTestCases();
     78     test();
     79 
     80 function getTestCases() {
     81     var array = new Array();
     82     var item = 0;
     83 
     84     // Georgian
     85     // Range: U+10A0 to U+10FF
     86     for ( var i = 0x10A0; i <= 0x10FF; i++ ) {
     87         var U = new Array(new Unicode( i, 4 ), new Unicode( i, 5 ));
     88 
     89 /*
     90         array[item++] = new TestCase(   SECTION,
     91                                         "var s = new String( String.fromCharCode("+i+") ); s.toLowerCase()",
     92                                         String.fromCharCode(U.lower),
     93                                         eval("var s = new String( String.fromCharCode("+i+") ); s.toLowerCase()") );
     94 */
     95         array[item++] = new TestCaseDualExpected(   SECTION,
     96                                         "var s = new String( String.fromCharCode("+i+") ); s.toLowerCase().charCodeAt(0)",
     97                                         U,
     98                                         eval("var s = new String( String.fromCharCode(i) ); s.toLowerCase().charCodeAt(0)") );
     99     }
    100 
    101     return array;
    102 }
    103 
    104 /*
    105  * TestCase constructor
    106  *
    107  */
    108 
    109 function TestCaseDualExpected( n, d, e, a ) {
    110     this.name        = n;
    111     this.description = d;
    112     this.expect      = e;
    113     this.actual      = a;
    114     this.passed      = true;
    115     this.reason      = "";
    116     this.bugnumber   = BUGNUMBER;
    117 
    118     this.passed = getTestCaseResultDualExpected( this.expect, this.actual );
    119     if ( DEBUG ) {
    120         writeLineToLog( "added " + this.description );
    121     }
    122 }
    123 
    124 // Added so that either Unicode 4.0 or 5.0 results will be considered correct.
    125 function writeTestCaseResultDualExpected( expect, actual, string ) {
    126         var passed = getTestCaseResultDualExpected( expect, actual );
    127         writeFormattedResult( expect[1].lower, actual, string, passed );
    128         return passed;
    129 }
    130 /*
    131  * Added so that either Unicode 4.0 or 5.0 results will be considered correct.
    132  * Compare expected result to the actual result and figure out whether
    133  * the test case passed.
    134  */
    135 function getTestCaseResultDualExpected( expect, actual ) {
    136     expectedU4 = expect[0].lower;
    137     expectedU5 = expect[1].lower;
    138     //  because ( NaN == NaN ) always returns false, need to do
    139     //  a special compare to see if we got the right result.
    140         if ( actual != actual ) {
    141             if ( typeof actual == "object" ) {
    142                 actual = "NaN object";
    143             } else {
    144                 actual = "NaN number";
    145             }
    146         }
    147 
    148         if ( expectedU4 != expectedU4 )   {
    149             if ( typeof expectedU4 == "object" ) {
    150                 expectedU4 = "NaN object";
    151             } else {
    152                 expectedU4 = "NaN number";
    153             }
    154         }
    155         if ( expectedU5 != expectedU5 )   {
    156             if ( typeof expectedU5 == "object" ) {
    157                 expectedU5 = "NaN object";
    158             } else {
    159                 expectedU5 = "NaN number";
    160             }
    161         }
    162 
    163         var passed = ( expectedU4 == actual || expectedU5 == actual ) ? true : false;
    164 
    165         //  if both objects are numbers
    166         // need to replace w/ IEEE standard for rounding
    167         if ( !passed &&
    168              typeof(actual) == "number" &&
    169             (typeof(expectedU4) == "number" ||
    170              typeof(expectedU5) == "number")) {
    171             if (( Math.abs(actual-expectedU4) < 0.0000001 ) || ( Math.abs(actual-expectedU5) < 0.0000001 )) {
    172                 passed = true;
    173             }
    174         }
    175 
    176         //  verify type is the same
    177         if ( typeof(expectedU4) != typeof(actual) && typeof(expectedU5) != typeof(actual) )   {
    178             passed = false;
    179         }
    180 
    181         return passed;
    182 }
    183 
    184 function test() {
    185     for ( tc=0; tc < testcases.length; tc++ ) {
    186         testcases[tc].passed = writeTestCaseResultDualExpected(
    187                             testcases[tc].expect,
    188                             testcases[tc].actual,
    189                             testcases[tc].description +" = "+ testcases[tc].actual );
    190 
    191         testcases[tc].reason += ( testcases[tc].passed ) ? "" : "wrong value ";
    192     }
    193     stopTest();
    194     return ( testcases );
    195 }
    196 
    197 function MyObject( value ) {
    198     this.value = value;
    199     this.substring = String.prototype.substring;
    200     this.toString = new Function ( "return this.value+''" );
    201 }
    202 
    203 function Unicode( c, version ) {
    204     u = GetUnicodeValues( c, version );
    205     this.upper = u[0];
    206     this.lower = u[1]
    207     return this;
    208 }
    209 
    210 function GetUnicodeValues( c, version ) {
    211     u = new Array();
    212 
    213     u[0] = c;
    214     u[1] = c;
    215 
    216     // upper case Basic Latin
    217 
    218     if ( c >= 0x0041 && c <= 0x005A) {
    219         u[0] = c;
    220         u[1] = c + 32;
    221         return u;
    222     }
    223 
    224     // lower case Basic Latin
    225     if ( c >= 0x0061 && c <= 0x007a ) {
    226         u[0] = c - 32;
    227         u[1] = c;
    228         return u;
    229     }
    230 
    231     // upper case Latin-1 Supplement
    232     if ( c == 0x00B5 ) {
    233         u[0] = c;
    234         u[1] = 0x039C;
    235         return u;
    236     }
    237     if ( (c >= 0x00C0 && c <= 0x00D6) || (c >= 0x00D8 && c<=0x00DE) ) {
    238         u[0] = c;
    239         u[1] = c + 32;
    240         return u;
    241     }
    242 
    243     // lower case Latin-1 Supplement
    244     if ( (c >= 0x00E0 && c <= 0x00F6) || (c >= 0x00F8 && c <= 0x00FE) ) {
    245         u[0] = c - 32;
    246         u[1] = c;
    247         return u;
    248     }
    249     if ( c == 0x00FF ) {
    250         u[0] = 0x0178;
    251         u[1] = c;
    252         return u;
    253     }
    254     // Latin Extended A
    255     if ( (c >= 0x0100 && c < 0x0138) || (c > 0x0149 && c < 0x0178) ) {
    256         // special case for capital I
    257         if ( c == 0x0130 ) {
    258             u[0] = c;
    259             u[1] = 0x0069;
    260             return u;
    261         }
    262         if ( c == 0x0131 ) {
    263             u[0] = 0x0049;
    264             u[1] = c;
    265             return u;
    266         }
    267 
    268         if ( c % 2 == 0 ) {
    269         // if it's even, it's a capital and the lower case is c +1
    270             u[0] = c;
    271             u[1] = c+1;
    272         } else {
    273         // if it's odd, it's a lower case and upper case is c-1
    274             u[0] = c-1;
    275             u[1] = c;
    276         }
    277         return u;
    278     }
    279     if ( c == 0x0178 ) {
    280         u[0] = c;
    281         u[1] = 0x00FF;
    282         return u;
    283     }
    284 
    285     if ( (c >= 0x0139 && c < 0x0149) || (c > 0x0178 && c < 0x017F) ) {
    286         if ( c % 2 == 1 ) {
    287         // if it's odd, it's a capital and the lower case is c +1
    288             u[0] = c;
    289             u[1] = c+1;
    290         } else {
    291         // if it's even, it's a lower case and upper case is c-1
    292             u[0] = c-1;
    293             u[1] = c;
    294         }
    295         return u;
    296     }
    297     if ( c == 0x017F ) {
    298         u[0] = 0x0053;
    299         u[1] = c;
    300     }
    301 
    302     // Latin Extended B
    303     // need to improve this set
    304 
    305     if ( c >= 0x0200 && c <= 0x0217 ) {
    306         if ( c % 2 == 0 ) {
    307             u[0] = c;
    308             u[1] = c+1;
    309         } else {
    310             u[0] = c-1;
    311             u[1] = c;
    312         }
    313         return u;
    314     }
    315 
    316     // Latin Extended Additional
    317     // Range: U+1E00 to U+1EFF
    318     // http://www.unicode.org/Unicode.charts/glyphless/U1E00.html
    319 
    320     // Spacing Modifier Leters
    321     // Range: U+02B0 to U+02FF
    322 
    323     // Combining Diacritical Marks
    324     // Range: U+0300 to U+036F
    325 
    326     // skip Greek for now
    327     // Greek
    328     // Range: U+0370 to U+03FF
    329 
    330     // Cyrillic
    331     // Range: U+0400 to U+04FF
    332 
    333     if ( c >= 0x0400 && c <= 0x040F) {
    334         u[0] = c;
    335         u[1] = c + 80;
    336         return u;
    337     }
    338 
    339 
    340     if ( c >= 0x0410  && c <= 0x042F ) {
    341         u[0] = c;
    342         u[1] = c + 32;
    343         return u;
    344     }
    345 
    346     if ( c >= 0x0430 && c<= 0x044F ) {
    347         u[0] = c - 32;
    348         u[1] = c;
    349         return u;
    350 
    351     }
    352     if ( c >= 0x0450 && c<= 0x045F ) {
    353         u[0] = c -80;
    354         u[1] = c;
    355         return u;
    356     }
    357 
    358     if ( c >= 0x0460 && c <= 0x047F ) {
    359         if ( c % 2 == 0 ) {
    360             u[0] = c;
    361             u[1] = c +1;
    362         } else {
    363             u[0] = c - 1;
    364             u[1] = c;
    365         }
    366         return u;
    367     }
    368 
    369     // Armenian
    370     // Range: U+0530 to U+058F
    371     if ( c >= 0x0531 && c <= 0x0556 ) {
    372         u[0] = c;
    373         u[1] = c + 48;
    374         return u;
    375     }
    376     if ( c >= 0x0561 && c < 0x0587 ) {
    377         u[0] = c - 48;
    378         u[1] = c;
    379         return u;
    380     }
    381 
    382     // Hebrew
    383     // Range: U+0590 to U+05FF
    384 
    385 
    386     // Arabic
    387     // Range: U+0600 to U+06FF
    388 
    389     // Devanagari
    390     // Range: U+0900 to U+097F
    391 
    392 
    393     // Bengali
    394     // Range: U+0980 to U+09FF
    395 
    396 
    397     // Gurmukhi
    398     // Range: U+0A00 to U+0A7F
    399 
    400 
    401     // Gujarati
    402     // Range: U+0A80 to U+0AFF
    403 
    404 
    405     // Oriya
    406     // Range: U+0B00 to U+0B7F
    407     // no capital / lower case
    408 
    409 
    410     // Tamil
    411     // Range: U+0B80 to U+0BFF
    412     // no capital / lower case
    413 
    414 
    415     // Telugu
    416     // Range: U+0C00 to U+0C7F
    417     // no capital / lower case
    418 
    419 
    420     // Kannada
    421     // Range: U+0C80 to U+0CFF
    422     // no capital / lower case
    423 
    424 
    425     // Malayalam
    426     // Range: U+0D00 to U+0D7F
    427 
    428     // Thai
    429     // Range: U+0E00 to U+0E7F
    430 
    431 
    432     // Lao
    433     // Range: U+0E80 to U+0EFF
    434 
    435 
    436     // Tibetan
    437     // Range: U+0F00 to U+0FBF
    438 
    439     // Georgian
    440     // Range: U+10A0 to U+10F0
    441     if ( version == 5 ) {
    442         if ( c >= 0x10A0 && c <= 0x10C5 ) {
    443             u[0] = c;
    444             u[1] = c + 7264; //48;
    445             return u;
    446         }
    447         if ( c >= 0x2D00 && c <= 0x2D25 ) {
    448             u[0] = c;
    449             u[1] = c;
    450             return u;
    451         }
    452     }
    453 
    454     // Hangul Jamo
    455     // Range: U+1100 to U+11FF
    456 
    457     // Greek Extended
    458     // Range: U+1F00 to U+1FFF
    459     // skip for now
    460 
    461 
    462     // General Punctuation
    463     // Range: U+2000 to U+206F
    464 
    465     // Superscripts and Subscripts
    466     // Range: U+2070 to U+209F
    467 
    468     // Currency Symbols
    469     // Range: U+20A0 to U+20CF
    470 
    471 
    472     // Combining Diacritical Marks for Symbols
    473     // Range: U+20D0 to U+20FF
    474     // skip for now
    475 
    476 
    477     // Number Forms
    478     // Range: U+2150 to U+218F
    479     // skip for now
    480 
    481 
    482     // Arrows
    483     // Range: U+2190 to U+21FF
    484 
    485     // Mathematical Operators
    486     // Range: U+2200 to U+22FF
    487 
    488     // Miscellaneous Technical
    489     // Range: U+2300 to U+23FF
    490 
    491     // Control Pictures
    492     // Range: U+2400 to U+243F
    493 
    494     // Optical Character Recognition
    495     // Range: U+2440 to U+245F
    496 
    497     // Enclosed Alphanumerics
    498     // Range: U+2460 to U+24FF
    499 
    500     // Box Drawing
    501     // Range: U+2500 to U+257F
    502 
    503     // Block Elements
    504     // Range: U+2580 to U+259F
    505 
    506     // Geometric Shapes
    507     // Range: U+25A0 to U+25FF
    508 
    509     // Miscellaneous Symbols
    510     // Range: U+2600 to U+26FF
    511 
    512     // Dingbats
    513     // Range: U+2700 to U+27BF
    514 
    515     // CJK Symbols and Punctuation
    516     // Range: U+3000 to U+303F
    517 
    518     // Hiragana
    519     // Range: U+3040 to U+309F
    520 
    521     // Katakana
    522     // Range: U+30A0 to U+30FF
    523 
    524     // Bopomofo
    525     // Range: U+3100 to U+312F
    526 
    527     // Hangul Compatibility Jamo
    528     // Range: U+3130 to U+318F
    529 
    530     // Kanbun
    531     // Range: U+3190 to U+319F
    532 
    533 
    534     // Enclosed CJK Letters and Months
    535     // Range: U+3200 to U+32FF
    536 
    537     // CJK Compatibility
    538     // Range: U+3300 to U+33FF
    539 
    540     // Hangul Syllables
    541     // Range: U+AC00 to U+D7A3
    542 
    543     // High Surrogates
    544     // Range: U+D800 to U+DB7F
    545 
    546     // Private Use High Surrogates
    547     // Range: U+DB80 to U+DBFF
    548 
    549     // Low Surrogates
    550     // Range: U+DC00 to U+DFFF
    551 
    552     // Private Use Area
    553     // Range: U+E000 to U+F8FF
    554 
    555     // CJK Compatibility Ideographs
    556     // Range: U+F900 to U+FAFF
    557 
    558     // Alphabetic Presentation Forms
    559     // Range: U+FB00 to U+FB4F
    560 
    561     // Arabic Presentation Forms-A
    562     // Range: U+FB50 to U+FDFF
    563 
    564     // Combining Half Marks
    565     // Range: U+FE20 to U+FE2F
    566 
    567     // CJK Compatibility Forms
    568     // Range: U+FE30 to U+FE4F
    569 
    570     // Small Form Variants
    571     // Range: U+FE50 to U+FE6F
    572 
    573     // Arabic Presentation Forms-B
    574     // Range: U+FE70 to U+FEFF
    575 
    576     // Halfwidth and Fullwidth Forms
    577     // Range: U+FF00 to U+FFEF
    578 
    579     if ( c >= 0xFF21 && c <= 0xFF3A ) {
    580         u[0] = c;
    581         u[1] = c + 32;
    582         return u;
    583     }
    584 
    585     if ( c >= 0xFF41 && c <= 0xFF5A ) {
    586         u[0] = c - 32;
    587         u[1] = c;
    588         return u;
    589     }
    590 
    591     // Specials
    592     // Range: U+FFF0 to U+FFFF
    593 
    594     return u;
    595 }
    596 
    597 function DecimalToHexString( n ) {
    598     n = Number( n );
    599     var h = "0x";
    600 
    601     for ( var i = 3; i >= 0; i-- ) {
    602         if ( n >= Math.pow(16, i) ){
    603             var t = Math.floor( n  / Math.pow(16, i));
    604             n -= t * Math.pow(16, i);
    605             if ( t >= 10 ) {
    606                 if ( t == 10 ) {
    607                     h += "A";
    608                 }
    609                 if ( t == 11 ) {
    610                     h += "B";
    611                 }
    612                 if ( t == 12 ) {
    613                     h += "C";
    614                 }
    615                 if ( t == 13 ) {
    616                     h += "D";
    617                 }
    618                 if ( t == 14 ) {
    619                     h += "E";
    620                 }
    621                 if ( t == 15 ) {
    622                     h += "F";
    623                 }
    624             } else {
    625                 h += String( t );
    626             }
    627         } else {
    628             h += "0";
    629         }
    630     }
    631 
    632     return h;
    633 }