[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r9522: Implement String.split more correctly. Document.,
Benjamin Wolsey <=