gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r9522: Implement String.split more c


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r9522: Implement String.split more correctly. Document.
Date: Wed, 23 Jul 2008 09:57:26 +0200
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 9522
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Wed 2008-07-23 09:57:26 +0200
message:
  Implement String.split more correctly. Document.
modified:
  gui/gtk_glue.h
  libcore/asobj/String_as.cpp
  testsuite/actionscript.all/String.as
    ------------------------------------------------------------
    revno: 9516.1.1
    committer: Benjamin Wolsey <address@hidden>
    branch nick: workingcopy
    timestamp: Tue 2008-07-22 11:22:09 +0200
    message:
      Pre-work cleanup.
    modified:
      server/asobj/String_as.cpp
    ------------------------------------------------------------
    revno: 9516.1.2
    committer: Benjamin Wolsey <address@hidden>
    branch nick: workingcopy
    timestamp: Tue 2008-07-22 11:22:24 +0200
    message:
      Make header guard legal.
    modified:
      gui/gtk_glue.h
    ------------------------------------------------------------
    revno: 9516.1.3
    committer: Benjamin Wolsey <address@hidden>
    branch nick: workingcopy
    timestamp: Tue 2008-07-22 11:39:27 +0200
    message:
      Temporarily split string_split by version.
    modified:
      server/asobj/String_as.cpp
    ------------------------------------------------------------
    revno: 9516.1.4
    committer: Benjamin Wolsey <address@hidden>
    branch nick: workingcopy
    timestamp: Tue 2008-07-22 14:36:52 +0200
    message:
      Test and implement String.split for SWF5.
    modified:
      server/asobj/String_as.cpp
      testsuite/actionscript.all/String.as
    ------------------------------------------------------------
    revno: 9516.1.5
    committer: Benjamin Wolsey <address@hidden>
    branch nick: workingcopy
    timestamp: Tue 2008-07-22 16:35:06 +0200
    message:
      More tests for string methods on objects.
    modified:
      testsuite/actionscript.all/String.as
    ------------------------------------------------------------
    revno: 9516.1.6
    committer: Benjamin Wolsey <address@hidden>
    branch nick: workingcopy
    timestamp: Tue 2008-07-22 17:00:54 +0200
    message:
      Merge from trunk
    modified:
      extensions/Makefile.am
      server/asobj/String_as.cpp
      testsuite/actionscript.all/String.as
    ------------------------------------------------------------
    revno: 9516.1.7
    committer: Benjamin Wolsey <address@hidden>
    branch nick: workingcopy
    timestamp: Tue 2008-07-22 18:04:13 +0200
    message:
      Add tests and implement split for SWF6+.
    modified:
      server/asobj/String_as.cpp
      testsuite/actionscript.all/String.as
    ------------------------------------------------------------
    revno: 9516.1.8
    committer: Benjamin Wolsey <address@hidden>
    branch nick: workingcopy
    timestamp: Tue 2008-07-22 18:20:24 +0200
    message:
      Partly merge string split implementations.
    modified:
      server/asobj/String_as.cpp
    ------------------------------------------------------------
    revno: 9516.1.9
    committer: Benjamin Wolsey <address@hidden>
    branch nick: workingcopy
    timestamp: Wed 2008-07-23 09:01:14 +0200
    message:
      Correct implementation of String.split for SWF6+, mark passing
      tests in actionscript.all/String.as.
    modified:
      server/asobj/String_as.cpp
      testsuite/actionscript.all/String.as
    ------------------------------------------------------------
    revno: 9516.1.10
    committer: Benjamin Wolsey <address@hidden>
    branch nick: workingcopy
    timestamp: Wed 2008-07-23 09:51:35 +0200
    message:
      Test that an undefined limit is the same as no limit for SWF6. Implement.
    modified:
      server/asobj/String_as.cpp
      testsuite/actionscript.all/String.as
=== modified file 'gui/gtk_glue.h'
--- a/gui/gtk_glue.h    2008-06-28 11:30:33 +0000
+++ b/gui/gtk_glue.h    2008-07-22 09:22:24 +0000
@@ -15,8 +15,8 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-#ifndef __GTK_GLUE_H__
-#define __GTK_GLUE_H__
+#ifndef GNASH_GTK_GLUE_H
+#define GNASH_GTK_GLUE_H
 
 #include "gnash.h"
 
@@ -48,5 +48,5 @@
 
 } // namespace gnash
 
-// end of __GTK_GLUE_H__
+// end of GNASH_GTK_GLUE_H
 #endif

=== modified file 'libcore/asobj/String_as.cpp'
--- a/libcore/asobj/String_as.cpp       2008-07-21 09:56:09 +0000
+++ b/libcore/asobj/String_as.cpp       2008-07-23 07:51:35 +0000
@@ -251,69 +251,114 @@
     return as_value(utf8::encodeCanonicalString(wstr.substr(start, retlen), 
version));
 }
 
+// String.split(delimiter[, limit])
+// For SWF5, the following conditions mean that an array with a single
+// element containing the entire string is returned:
+// 1. No arguments are passed.
+// 2. The delimiter is empty.
+// 3. The delimiter has more than one character or is undefined and limit is 
not 0.
+// 4. The delimiter is not present in the string and the limit is not 0.
+//
+// Accordingly, an empty array is returned only when the limit is less
+// than 0 and a non-empty delimiter is passed.
+//
+// For SWF6:
+// Full string returned in 1-element array:
+// 1. If no arguments are passed.
+// 2. If delimiter undefined.
+// 3: empty string, non-empty delimiter.
+//
+// Empty array returned:
+// 4. string and delimiter are empty but defined.
+// 5. non-empty string, non-empty delimiter; 0 or less elements required.
 static as_value
 string_split(const fn_call& fn)
 {
-    boost::intrusive_ptr<string_as_object> obj =
-        ensureType<string_as_object>(fn.this_ptr);
-
-    VM& vm = obj->getVM(); 
-    int SWFVersion = vm.getSWFVersion();
-
-    std::wstring wstr = utf8::decodeCanonicalString(obj->str(), SWFVersion);
-
-    as_value val;
+    boost::intrusive_ptr<string_as_object> obj =  
ensureType<string_as_object>(fn.this_ptr);
+
+    const int version = obj->getVM().getSWFVersion();
+    
+    const std::string& str = obj->str();
+
+    std::wstring wstr = utf8::decodeCanonicalString(str, version);
 
     boost::intrusive_ptr<as_array_object> array(new as_array_object());
 
     if (fn.nargs == 0)
     {
-        val.set_std_string(obj->str());
-        array->push(val);
-
-        return as_value(array.get());
-    }
-
-    const std::wstring& delim = 
utf8::decodeCanonicalString(fn.arg(0).to_string(), SWFVersion);
-
-    // SWF5 didn't support multichar or empty delimiter
-    if ( SWFVersion < 6 )
-    {
-           if ( delim.size() != 1 )
-           {
-                   val.set_std_string(obj->str());
-                   array->push(val);
-                   return as_value(array.get());
-           }
-    }
-
-    size_t max = wstr.size();
-
-    if (fn.nargs >= 2)
-    {
-       int max_in = fn.arg(1).to_int();
-       if ( SWFVersion < 6 && max_in < 1 )
-       {
-               return as_value(array.get());
-       }
-        max = utility::clamp<size_t>(max_in, 0, wstr.size());
-    }
-
-    if ( wstr.empty() )
-    {
-        val.set_std_string(obj->str());
-        array->push(val);
-
-        return as_value(array.get());
-    }
-
-    if ( delim.empty() ) {
-        for (unsigned i=0; i <max; i++) {
-            val.set_std_string(utf8::encodeCanonicalString(wstr.substr(i, 1), 
SWFVersion));
-            array->push(val);
-        }
-
-        return as_value(array.get());
+        // Condition 1:
+        array->push(str);
+        return as_value(array.get());
+    }
+
+    const std::wstring& delim = 
utf8::decodeCanonicalString(fn.arg(0).to_string(), version);
+    const size_t delimiterSize = delim.size();
+
+    if ((version < 6 && delimiterSize == 0) ||
+        (version >= 6 && fn.arg(0).is_undefined()))
+    {
+        // Condition 2:
+        array->push(str);
+        return as_value(array.get());
+    }
+
+    size_t max = wstr.size() + 1;
+
+    if (version < 6)
+    {
+        // SWF5
+        if (fn.nargs > 1 && !fn.arg(1).is_undefined())
+        {
+            int limit = fn.arg(1).to_int();
+            if (limit < 1)
+            {
+                // Return empty array.
+                return as_value(array.get());
+            }
+            max = utility::clamp<size_t>(limit, 0, max);
+        }
+
+        if (delimiterSize > 1 || fn.arg(0).is_undefined() || wstr.empty())
+        {
+            // Condition 3 (plus a shortcut if the string itself
+            // is empty).
+               array->push(str);
+               return as_value(array.get());            
+        }
+    }
+    else
+    {
+        // SWF6+
+        if (wstr.empty())
+        {
+            // If the string itself is empty, SWF6 returns a 0-sized
+            // array only if the delimiter is also empty. Otherwise
+            // it returns an array with 1 empty element.
+            if (delimiterSize) array->push(str);
+            return as_value(array.get());
+        }
+
+        // If we reach this point, the string is not empty and
+        // the delimiter is defined.
+        if (fn.nargs > 1 && !fn.arg(1).is_undefined())
+        {
+               int limit = fn.arg(1).to_int();
+               if (limit < 1) {
+                   // Return empty array if 
+                   return as_value(array.get());
+               }
+            max = utility::clamp<size_t>(limit, 0, max);
+        }
+
+        // If the delimiter is empty, put each character in an
+        // array element.
+        if ( delim.empty() ) {
+            for (size_t i = 0, e = wstr.size(); i < e; ++i) {
+                array->push(utf8::encodeCanonicalString(wstr.substr(i, 1), 
version));
+            }
+            return as_value(array.get());
+        }
+
     }
 
     size_t pos = 0, prevpos = 0;
@@ -322,21 +367,13 @@
     while (num < max) {
         pos = wstr.find(delim, pos);
 
-        if (pos != std::wstring::npos) {
-            val.set_std_string(utf8::encodeCanonicalString(
-                       wstr.substr(prevpos, pos - prevpos),
-                       SWFVersion));
-            array->push(val);
+        array->push(utf8::encodeCanonicalString(
+                               wstr.substr(prevpos, pos - prevpos),
+                               version));
+            if (pos == std::wstring::npos) break;
             num++;
-            prevpos = pos + delim.size();
+            prevpos = pos + delimiterSize;
             pos++;
-        } else {
-            val.set_std_string(utf8::encodeCanonicalString(
-                       wstr.substr(prevpos),
-                       SWFVersion));
-            array->push(val);
-            break;
-        }
     }
 
     return as_value(array.get());

=== modified file 'testsuite/actionscript.all/String.as'
--- a/testsuite/actionscript.all/String.as      2008-07-22 14:44:47 +0000
+++ b/testsuite/actionscript.all/String.as      2008-07-23 07:51:35 +0000
@@ -116,7 +116,6 @@
 xcheck_equals(c, "e");
 c = o.charCodeAt(4);
 xcheck_equals(c, "101");
-
 //----------------------------------------
 // Check String.indexOf
 // TODO: test with ASnative(251,8)
@@ -151,7 +150,6 @@
 o.indexOf = String.prototype.indexOf;
 p = o.indexOf("b");
 xcheck_equals(p, 2);
-
 //----------------------------------------
 // Check String.split
 // See ASNative.as for more tests.
@@ -171,7 +169,18 @@
 check_equals ( a.split("  w").length, 1);
 
 #if OUTPUT_VERSION > 5
-// TODO: check more of split(''), it seems to be bogus !
+// For SWF6 and above the following condititions apply in
+// this order:
+// Full string returned in 1-element array:
+// 1. If no arguments are passed.
+// 2. If delimiter undefined.
+// 3: empty string, non-empty delimiter.
+//
+// Empty array returned:
+// 4. string and delimiter are empty but defined.
+// 5. non-empty string, non-empty delimiter; 0 or less elements required.
+//
+// If the delimiter is empty, each character is placed in a separate element.
 ret = a.split('');
 check_equals(typeof(ret), 'object');
 check(ret instanceof Array);
@@ -187,27 +196,163 @@
 check_equals ( a.split("la")[2], "washinGTON" );
 check_equals ( a.split("la").length, 3 );
 
+str = "h";
+ar = str.split("h");
+check_equals(ar.length, 2);
+check_equals(ar.toString(), ",");
+
+str = "";
+ar = str.split("h");
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "");
+
+str = "hh";
+ar = str.split("h");
+check_equals(ar.length, 3);
+check_equals(ar.toString(), ",,");
+
+str = "h";
+ar = str.split("g");
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "h");
+
+str = "a";
+ar = str.split("aa");
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "a");
+
+str = "b";
+ar = str.split("aa");
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "b");
+
+str = "a";
+ar = str.split("aa");
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "a");
+
+str = "aa";
+ar = str.split("aa");
+check_equals(ar.length, 2);
+check_equals(ar.toString(), ",");
+
+str = "";
+ar = str.split("");
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
+
+str = "b";
+ar = str.split("");
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "b");
+
+str = "aa";
+ar = str.split("");
+check_equals(ar.length, 2);
+check_equals(ar.toString(), "a,a");
+
+str = "";
+ar = str.split();
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "");
+
+str = "b";
+ar = str.split();
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "b");
+
+str = "aa";
+ar = str.split();
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "aa");
+
+
+// Limit 0 or less:
+str = "aa";
+ar = str.split("", 0);
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
+
+str = "";
+ar = str.split("x", 0);
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "");
+
+str = "";
+ar = str.split("x", -1);
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "");
+
+str = "";
+ar = str.split("", 0);
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
+
+str = "";
+ar = str.split("", -1);
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
+
+str = "aa";
+ar = str.split("", -1);
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
+
+str = "aa";
+ar = str.split("aa", 0);
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
+
+str = "aa";
+ar = str.split("aa", -1);
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
+
+str = "aa";
+ar = str.split(undefined, 0);
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "aa");
+
+str = "aa";
+ar = str.split("a", 0);
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
+
+// Limit undefined
+str = "aa";
+ar = str.split("aa", undefined);
+check_equals(ar.length, 2);
+check_equals(ar.toString(), ",");
+
+// String methods on object.
 o = new Object;
 o.split = String.prototype.split;
 ar = o.split("b");
 xcheck_equals(ar.length, 3);
 xcheck_equals(ar.toString(), "[o,ject O,ject]");
 
+o = new Date(0);
+o.split = String.prototype.split;
+ar = o.split(":");
+xcheck_equals(ar.length, 3);
+
+
 #else
+// SWF5:
+
 // empty delimiter doesn't have a special meaning in SWF5
 check_equals ( a.split("")[0], "wallawallawashinGTON" );
 check_equals ( a.split("")[19], undefined );
-// mulit-char delimiter doesn't work in SWF5
+// multi-char delimiter doesn't work in SWF5
 check_equals ( a.split("la")[0], "wallawallawashinGTON" );
 check_equals ( a.split("la")[1], undefined );
 check_equals ( a.split("la")[2], undefined );
 check_equals ( a.split("la").length, 1 );
 
-// SWF5:
 str = "h";
 ar = str.split("h");
-xcheck_equals(ar.length, 2);
-xcheck_equals(ar.toString(), ",");
+check_equals(ar.length, 2);
+check_equals(ar.toString(), ",");
 
 str = "";
 ar = str.split("h");
@@ -216,8 +361,8 @@
 
 str = "hh";
 ar = str.split("h");
-xcheck_equals(ar.length, 3);
-xcheck_equals(ar.toString(), ",,");
+check_equals(ar.length, 3);
+check_equals(ar.toString(), ",,");
 
 str = "h";
 ar = str.split("g");
@@ -295,26 +440,52 @@
 check_equals(ar.length, 1);
 check_equals(ar.toString(), "aa");
 
+str = "";
+ar = str.split("x", 0);
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
+
+str = "";
+ar = str.split("x", -1);
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
+
+str = "";
+ar = str.split("", 0);
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "");
+
+str = "";
+ar = str.split("", -1);
+check_equals(ar.length, 1);
+check_equals(ar.toString(), "");
+
 str = "aa";
 ar = str.split("aa", 0);
-xcheck_equals(ar.length, 0);
-xcheck_equals(ar.toString(), "");
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
 
 str = "aa";
 ar = str.split("aa", -1);
-xcheck_equals(ar.length, 0);
-xcheck_equals(ar.toString(), "");
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
 
 str = "aa";
 ar = str.split(undefined, 0);
-xcheck_equals(ar.length, 0);
-xcheck_equals(ar.toString(), "");
+check_equals(ar.length, 0);
+check_equals(ar.toString(), "");
 
 str = "aa";
 ar = str.split("a", 0);
 check_equals(ar.length, 0);
 check_equals(ar.toString(), "");
 
+// Limit undefined
+str = "aa";
+ar = str.split("a", undefined);
+check_equals(ar.length, 3);
+check_equals(ar.toString(), ",,");
+
 o = new Object;
 o.split = String.prototype.split;
 ar = o.split("b");
@@ -365,9 +536,9 @@
 st = "";
 g = st.split("", 0);
 #if OUTPUT_VERSION > 5
-xcheck_equals(g.length, 0);
-xcheck_equals(typeof(g[0]), "undefined");
-xcheck_equals(g[0], undefined);
+check_equals(g.length, 0);
+check_equals(typeof(g[0]), "undefined");
+check_equals(g[0], undefined);
 #else
 check_equals(g.length, 1);
 check_equals(typeof(g[0]), "string");
@@ -988,11 +1159,21 @@
     return "fake to string";
 };
 
+Object.prototype.toString = function ()
+{
+    return "fake object";
+};
+
 g = "teststring";
 check_equals (g.substr(0,4), "test");
 g = new String("teststring");
 check_equals (g.substr(0,4), "test");
 
+o = new Object;
+check_equals(o.substr(0,4), undefined);
+o.substr = String.prototype.substr;
+xcheck_equals(o.substr(0,4), "fake");
+
 Object.prototype.toString = ObjectProtoToStringBackup;
 String.prototype.toString = StringProtoToStringBackup;
 
@@ -1087,7 +1268,7 @@
 #endif
 
 #if OUTPUT_VERSION < 6
- check_totals(311);
+ check_totals(323);
 #else
- check_totals(286);
+ check_totals(339);
 #endif


reply via email to

[Prev in Thread] Current Thread [Next in Thread]