gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash ./ChangeLog server/Function.cpp server/Ob...


From: strk
Subject: [Gnash-commit] gnash ./ChangeLog server/Function.cpp server/Ob...
Date: Thu, 27 Apr 2006 16:31:57 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Branch:         
Changes by:     strk <address@hidden>   06/04/27 16:31:56

Modified files:
        .              : ChangeLog 
        server         : Function.cpp Object.cpp Object.h action.h 
                         array.cpp array.h 
        testsuite/actionscript.all: array.as 

Log message:
        * server/: (array.cpp, array.h): big cleanup, provided
        overrides for get_member() and set_member() to add support
        for the special 'length' element, turned array_as_object into
        a real class.
        * server/: (Object.cpp, Object.h): moved get_member
        and set_member to get_member_default and set_member_default
        with protected access level, provided public virtuals
        invoking the protected non-virtuals. This is to allow cleaner
        hooking for ActionScript classes.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/ChangeLog.diff?tr1=1.248&tr2=1.249&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/Function.cpp.diff?tr1=1.12&tr2=1.13&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/Object.cpp.diff?tr1=1.9&tr2=1.10&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/Object.h.diff?tr1=1.8&tr2=1.9&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/action.h.diff?tr1=1.27&tr2=1.28&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/array.cpp.diff?tr1=1.18&tr2=1.19&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/array.h.diff?tr1=1.6&tr2=1.7&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/testsuite/actionscript.all/array.as.diff?tr1=1.5&tr2=1.6&r1=text&r2=text

Patches:
Index: gnash/ChangeLog
diff -u gnash/ChangeLog:1.248 gnash/ChangeLog:1.249
--- gnash/ChangeLog:1.248       Thu Apr 27 15:31:18 2006
+++ gnash/ChangeLog     Thu Apr 27 16:31:56 2006
@@ -22,7 +22,8 @@
 
        * testsuite/actionscript.all/array.as: turned length()
        method calls to length data member accesses, completed
-       switch to check_equals() macro usage.
+       switch to check_equals() macro usage, removed .pop() calls
+       in macro args (would have unexpected results when macro fails).
        * server/: (Function.h, Function.cpp): added new constructor
        taking exported interface as argument.
        * server/: (System.cpp, System.h, Global.cpp): added System
@@ -32,6 +33,15 @@
        * doc/C/internals.xml: added note about check_equals() macro
        under testing section.
        * server/: (Sound.cpp, Sound.h): added missing files
+       * server/: (array.cpp, array.h): big cleanup, provided
+       overrides for get_member() and set_member() to add support
+       for the special 'length' element, turned array_as_object into
+       a real class.
+       * server/: (Object.cpp, Object.h): moved get_member
+       and set_member to get_member_default and set_member_default
+       with protected access level, provided public virtuals
+       invoking the protected non-virtuals. This is to allow cleaner
+       hooking for ActionScript classes.
 
 2006-04-26  Timo Lindfors <address@hidden>
 
Index: gnash/server/Function.cpp
diff -u gnash/server/Function.cpp:1.12 gnash/server/Function.cpp:1.13
--- gnash/server/Function.cpp:1.12      Thu Apr 27 08:41:45 2006
+++ gnash/server/Function.cpp   Thu Apr 27 16:31:56 2006
@@ -408,7 +408,7 @@
                                as_value index, value;
                                for (unsigned int i=nelems; i; i--)
                                {
-                                       value=arg_array->elements[i-1];
+                                       value=arg_array->at(i-1);
                                        //log_msg("value: %s\n", 
value.to_string());
                                        fn.env->push_val(value);
                                        pushed++;
Index: gnash/server/Object.cpp
diff -u gnash/server/Object.cpp:1.9 gnash/server/Object.cpp:1.10
--- gnash/server/Object.cpp:1.9 Mon Apr 24 23:05:56 2006
+++ gnash/server/Object.cpp     Thu Apr 27 16:31:56 2006
@@ -48,9 +48,17 @@
 
 namespace gnash {
 
+/*public virtual*/
 bool
 as_object::get_member(const tu_stringi& name, as_value* val)
 {
+       return get_member_default(name, val);
+}
+
+/*protected*/
+bool
+as_object::get_member_default(const tu_stringi& name, as_value* val)
+{
        IF_VERBOSE_ACTION(
                log_msg("  get member: %s (at %p) for object %p\n", 
name.c_str(), val, this);
        );
@@ -94,7 +102,13 @@
 }
 
 void
-as_object::set_member(const tu_stringi& name, const as_value& val )
+as_object::set_member(const tu_stringi& name, const as_value& val)
+{
+       return set_member_default(name, val);
+}
+
+void
+as_object::set_member_default(const tu_stringi& name, const as_value& val )
 {
        //printf("SET MEMBER: %s at %p for object %p\n", name.c_str(), 
val.to_object(), this);
        if (name == "__proto__") 
Index: gnash/server/Object.h
diff -u gnash/server/Object.h:1.8 gnash/server/Object.h:1.9
--- gnash/server/Object.h:1.8   Mon Apr 24 23:05:56 2006
+++ gnash/server/Object.h       Thu Apr 27 16:31:56 2006
@@ -47,7 +47,7 @@
 
 namespace gnash {
 
-struct as_object;
+class as_object;
 struct fn_call;
 struct function_as_object;
 struct movie;
@@ -167,6 +167,14 @@
        }
 
        /// Construct a NUMBER value
+       as_value(unsigned int val)
+               :
+               m_type(NUMBER),
+               m_number_value(double(val))
+       {
+       }
+
+       /// Construct a NUMBER value
        as_value(float val)
                :
                m_type(NUMBER),
@@ -426,6 +434,7 @@
 
        /// set the value
        void set_member_value(const as_value &value)  { m_value = value; }
+
        /// accessor to the properties flags
        void set_member_flags(const as_prop_flags &flags)  { m_flags = flags; }
 };
@@ -464,8 +473,11 @@
 /// Base-class for ActionScript script-defined objects.
 /// This would likely be ActionScript's 'Object' class.
 ///
-struct as_object : public resource
+class as_object : public resource
 {
+
+public:
+
        /// Members of this objects in an hash
        stringi_hash<as_member> m_members;
 
@@ -499,7 +511,12 @@
                        const as_value& val );
 
        /// Get a member as_value by name
+       //
+       /// This is the one to be overridden if you need special
+       /// handling of some values.
+       ///
        virtual bool get_member(const tu_stringi& name, as_value* val);
+       
 
        /// Get an member pointer by name
        virtual bool get_member(const tu_stringi& name,
@@ -521,6 +538,13 @@
        /// work
        ///
        bool instanceOf(function_as_object* ctor);
+
+protected:
+       /// Get a member as_value by name
+       bool get_member_default(const tu_stringi& name, as_value* val);
+
+       /// Set a member value
+       void set_member_default(const tu_stringi& name, const as_value& val);
 };
 
 } // namespace gnash
Index: gnash/server/action.h
diff -u gnash/server/action.h:1.27 gnash/server/action.h:1.28
--- gnash/server/action.h:1.27  Wed Apr 26 22:10:09 2006
+++ gnash/server/action.h       Thu Apr 27 16:31:56 2006
@@ -60,7 +60,7 @@
 namespace gnash {
        struct movie;
        struct as_environment;
-       struct as_object;
+       class as_object;
        struct as_value;
        struct function_as_object;
 
Index: gnash/server/array.cpp
diff -u gnash/server/array.cpp:1.18 gnash/server/array.cpp:1.19
--- gnash/server/array.cpp:1.18 Wed Apr 26 22:10:09 2006
+++ gnash/server/array.cpp      Thu Apr 27 16:31:56 2006
@@ -48,6 +48,8 @@
 #endif
 
 #include <string>
+#include <algorithm>
+#include <memory> // for auto_ptr
 
 #include "array.h"
 #include "action.h"
@@ -58,16 +60,20 @@
 // @@ TODO : implement as_array_object's unimplemented functions
 
        as_array_object::as_array_object()
-               : elements(0)
+               :
+               as_object(), // should pass Array inheritance
+               elements(0)
        {
                array_init(this);
        }
 
-       const int as_array_object::size() const
+       as_array_object::as_array_object(const as_array_object& other)
+               :
+               as_object(other)
        {
-               return elements.size();
+               array_init(this);
        }
-       
+
        int as_array_object::index_requested(const tu_stringi& name)
        {
                double value;
@@ -84,45 +90,189 @@
                return int(value + 0.01);
        }
 
-       void as_array_object::set_member(const tu_stringi& name, const 
as_value& val )
+       void as_array_object::push(as_value& val)
        {
-               int index = index_requested(name);
+               elements.push_back(val);
+       }
 
-               if (index >= 0) // if we were sent a valid array index and not 
a normal member
+       void as_array_object::unshift(as_value& val)
+       {
+               elements.push_front(val);
+       }
+
+       as_value as_array_object::pop()
+       {
+               // If the array is empty, report an error and return undefined!
+               if (elements.size() <= 0)
                {
-                       if (index >= int(elements.size()))
-                               elements.resize(index+1); // if we're setting 
index (x), the vector must be size (x+1)
+                       IF_VERBOSE_ACTION(log_error("tried to pop element from 
back of empty array!\n"));
+                       return as_value(); // undefined
+               }
 
-                       // set the appropriate index and return
-                       elements[index] = val;
-                       return;
+               as_value ret = elements.back();
+               elements.pop_back();
+
+               return ret;
+       }
+
+       as_value as_array_object::shift()
+       {
+               // If the array is empty, report an error and return undefined!
+               if (elements.size() <= 0)
+               {
+                       IF_VERBOSE_ACTION(log_error("tried to shift element 
from front of empty array!\n"));
+                       return as_value(); // undefined
+               }
+
+               as_value ret = elements.front();
+               elements.pop_front();
+
+               return ret;
+       }
+
+       void as_array_object::reverse()
+       {
+               // Reverse the deque elements
+               std::reverse(elements.begin(), elements.end());
+
+#if 0 // using the standard algorithms
+               int i,j;
+               as_value temp;
+
+               for (i=0,j=int(array->elements.size())-1;i<j;i++,j--)
+               {
+                       temp = array->elements[i];
+                       array->elements[i] = array->elements[j];
+                       array->elements[j] = temp;
+               }
+#endif // 0
+       }
+
+       std::string as_array_object::join(const std::string& separator)
+       {
+               // TODO - confirm this is the right format!
+               // Reportedly, flash version 7 on linux, and Flash 8 on IE look 
like
+               // "(1,2,3)" and "1,2,3" respectively - which should we mimic?
+               // Using no parentheses until confirmed for sure
+//             std::string temp = "(";
+               std::string temp;
+
+               for (unsigned int i=0, n=elements.size()-1; i<n; i++)
+                       temp += elements[i].to_string() + separator;
+
+               // Add the last element without a trailing separator
+               if (elements.size() > 0)
+                       temp += elements.back().to_string();
+
+//             temp = temp + ")";
+
+               return temp;
+
+       }
+
+       void as_array_object::concat(const as_array_object& other)
+       {
+               elements.insert(elements.end(), other.elements.begin(),
+                       other.elements.end());
+       }
+
+       std::string as_array_object::toString()
+       {
+               return join(",");
+       }
+
+       unsigned int as_array_object::size() const
+       {
+               return elements.size();
+       }
+
+#if 0
+       void as_array_object::resize(unsigned int newsize)
+       {
+               elements.resize(newsize);
+       }
+#endif
+
+       as_value as_array_object::at(unsigned int index)
+       {
+               if ( index > elements.size()-1 )
+               {
+                       return as_value();
+               }
+               else
+               {
+                       return elements[index];
                }
+       }
+
+       std::auto_ptr<as_array_object>
+       as_array_object::slice(unsigned int start, unsigned int one_past_end)
+       {
+               std::auto_ptr<as_array_object> newarray(new as_array_object);
+               newarray->elements.resize(one_past_end - start - 1);
+
+               // maybe there's a standard algorithm for this ?
+               for (unsigned int i=start; i<one_past_end; ++i)
+               {
+                       newarray->elements[i-start] = elements[i];
+               }
+
+               return newarray;
 
-               as_object::set_member(name,val);
        }
 
+
+       /* virtual public, overriding as_object::set_member */
        bool as_array_object::get_member(const tu_stringi& name, as_value *val)
        {
+               if ( name == "length" ) 
+               {
+                       val->set_double((double)size());
+                       return true;
+               }
+
+               // an index has been requested
+               int index = index_requested(name);
+               if ( index >= 0 && (unsigned int)index < elements.size() )
+               {
+                       *val = elements[index];
+                       return true;
+               }
+
+               return get_member_default(name, val);
+       }
+
+       /* virtual public, overriding as_object::set_member */
+       void as_array_object::set_member(const tu_stringi& name,
+                       const as_value& val )
+       {
+               if ( name == "length" ) 
+               {
+                       IF_VERBOSE_ACTION(log_msg("assigning to Array.length 
unsupported"));
+                       return;
+               }
+
                int index = index_requested(name);
 
-               // if we found an array index
+               // if we were sent a valid array index and not a normal member
                if (index >= 0)
                {
-                       // let's return false if it exceeds the bounds of 
num_elements
                        if (index >= int(elements.size()))
-                               return false;
-                       // otherwise return the appropriate array index from 
the vector
-                       else
                        {
-                               *val = elements[index];
-                               return true;
+                               // if we're setting index (x), the vector
+                               // must be size (x+1)
+                               elements.resize(index+1);
                        }
+
+                       // set the appropriate index and return
+                       elements[index] = val;
+                       return;
                }
 
-               // We're past the array-specific stuff - let's proceed to the 
regular as_object::get_member() for default behavior
-               return as_object::get_member(name,val);
+               as_object::set_member_default(name,val);
        }
 
+
        // Callback for unimplemented functions
        void    array_not_impl(const fn_call& fn)
        {
@@ -145,7 +295,7 @@
                IF_VERBOSE_ACTION(log_msg("calling array push, pushing %d 
values onto back of array\n",fn.nargs));
 
                for (int i=0;i<fn.nargs;i++)
-                       array->elements.push_back(fn.arg(i));
+                       array->push(fn.arg(i));
 
                fn.result->set_int(array->size());
        }
@@ -157,7 +307,7 @@
                IF_VERBOSE_ACTION(log_msg("calling array unshift, pushing %d 
values onto front of array\n",fn.nargs));
 
                for (int i=fn.nargs-1;i>=0;i--)
-                       array->elements.push_front(fn.arg(i));
+                       array->unshift(fn.arg(i));
 
                fn.result->set_int(array->size());
        }
@@ -167,18 +317,9 @@
        {
                as_array_object* array = (as_array_object*) (as_object*) 
fn.this_ptr;
 
-               // If the array is empty, report an error and return undefined!
-               if (array->elements.size() <= 0)
-               {
-                       IF_VERBOSE_ACTION(log_error("tried to pop element from 
back of empty array!\n"));
-                       fn.result->set_undefined();
-                       return;
-               }
-
                // Get our index, log, then return result
-               (*fn.result) = array->elements[array->elements.size()-1];
-               array->elements.pop_back();
-               IF_VERBOSE_ACTION(log_msg("calling array pop, result:%s, new 
array size:%zd\n",fn.result->to_string(),array->elements.size()));
+               (*fn.result) = array->pop();
+               IF_VERBOSE_ACTION(log_msg("calling array pop, result:%s, new 
array size:%zd\n",fn.result->to_string(),array->size()));
        }
 
        // Callback to pop a value from the front of an array
@@ -186,18 +327,9 @@
        {
                as_array_object* array = (as_array_object*) (as_object*) 
fn.this_ptr;
 
-               // If the array is empty, report an error and return undefined!
-               if (array->elements.size() <= 0)
-               {
-                       IF_VERBOSE_ACTION(log_error("tried to shift element 
from front of empty array!\n"));
-                       fn.result->set_undefined();
-                       return;
-               }
-
                // Get our index, log, then return result
-               (*fn.result) = array->elements[0];
-               array->elements.pop_front();
-               IF_VERBOSE_ACTION(log_msg("calling array shift, result:%s, new 
array size:%zd\n",fn.result->to_string(),array->elements.size()));
+               (*fn.result) = array->shift();
+               IF_VERBOSE_ACTION(log_msg("calling array shift, result:%s, new 
array size:%zd\n",fn.result->to_string(),array->size()));
        }
 
        // Callback to reverse the position of the elements in an array
@@ -205,21 +337,12 @@
        {
                as_array_object* array = (as_array_object*) (as_object*) 
fn.this_ptr;
 
-               int i,j;
-               as_value temp;
+               array->reverse();
 
-               // Reverse the deque elements
-               for (i=0,j=int(array->elements.size())-1;i<j;i++,j--)
-               {
-                       temp = array->elements[i];
-                       array->elements[i] = array->elements[j];
-                       array->elements[j] = temp;
-               }
-               
-               IF_VERBOSE_ACTION(log_msg("calling array reverse on array with 
size:%zd\n",array->elements.size()));
+               fn.result->set_as_object(array);
 
-               // result is undefined
-               fn.result->set_undefined();
+               IF_VERBOSE_ACTION(log_msg("called array reverse, result:%s, new 
array size:%zd\n",fn.result->to_string(),array->size()));
+               
        }
 
        // Callback to convert array to a string with optional custom separator 
(default ',')
@@ -227,28 +350,14 @@
        {
                as_array_object* array = (as_array_object*) (as_object*) 
fn.this_ptr;
 
-               // TODO - confirm this is the right format!
-               // Reportedly, flash version 7 on linux, and Flash 8 on IE look 
like
-               // "(1,2,3)" and "1,2,3" respectively - which should we mimic?
-               // Using no parentheses until confirmed for sure
-//             std::string temp = "(";
-               std::string temp;
                std::string separator = ",";
-               int i;
 
                if (fn.nargs > 0)
                        separator = fn.arg(0).to_string();
 
-               for (i=0;i<int(array->elements.size()) - 1;i++)
-                       temp = temp + array->elements[i].to_string() + 
separator;
-
-               // Add the last element without a trailing separator
-               if (array->elements.size() > 0)
-                       temp = temp + array->elements[i].to_string();
+               std::string ret = array->join(separator);
 
-//             temp = temp + ")";
-
-               fn.result->set_string(temp.c_str());
+               fn.result->set_string(ret.c_str());
        }
 
        // Callback to convert array to a string
@@ -256,46 +365,47 @@
        {
                as_array_object* array = (as_array_object*) (as_object*) 
fn.this_ptr;
 
-               // TODO - confirm this is the right format!
-               // Reportedly, flash version 7 on linux, and Flash 8 on IE look 
like
-               // "(1,2,3)" and "1,2,3" respectively - which should we mimic?
-               // Using no parentheses until confirmed for sure
-//             std::string temp = "(";
-               std::string temp;
-               int i;
-
-               for (i=0;i<int(array->elements.size()) - 1;i++)
-                       temp = temp + array->elements[i].to_string() + ',';
-
-               // Add the last element without a trailing comma
-               if (array->elements.size() > 0)
-                       temp = temp + array->elements[i].to_string();
+               std::string ret = array->toString();
 
-//             temp = temp + ")";
-
-               fn.result->set_string(temp.c_str());
+               fn.result->set_string(ret.c_str());
        }
 
-       // Callback to convert array to a string
+       /// concatenates the elements specified in the parameters with
+       /// the elements in my_array, and creates a new array. If the
+       /// value parameters specify an array, the elements of that
+       /// array are concatenated, rather than the array itself. The
+       /// array my_array is left unchanged.
        void array_concat(const fn_call& fn)
        {
                as_array_object* array = (as_array_object*) (as_object*) 
fn.this_ptr;
-               as_array_object* newarray = new as_array_object;
-
-               newarray->elements = array->elements;
+               // use copy ctor
+               as_array_object* newarray = new as_array_object(*array);
 
-               for (int i=0;i<fn.nargs;i++)
-                       newarray->elements.push_back(fn.arg(i));
+               for (int i=0; i<fn.nargs; i++)
+               {
+                       // Array args get concatenated by elements
+                       if ( as_array_object* other = 
dynamic_cast<as_array_object*>(fn.arg(i).to_object()) )
+                       {
+                               assert(other);
+                               newarray->concat(*other);
+                       }
+                       else
+                       {
+                               newarray->push(fn.arg(i));
+                       }
+               }
 
                fn.result->set_as_object(newarray);             
        }
 
-       // Callback to slice part of an array to a new array without changing 
the original
+       // Callback to slice part of an array to a new array
+       // without changing the original
        void array_slice(const fn_call& fn)
        {
                as_array_object* array = (as_array_object*) (as_object*) 
fn.this_ptr;
 
-               int startindex,endindex; // start and end index of the part 
we're slicing
+               // start and end index of the part we're slicing
+               int startindex, endindex;
 
                if (fn.nargs > 2)
                {
@@ -303,64 +413,70 @@
                        IF_VERBOSE_ACTION(log_error("Ignoring them as we 
continue...\n"));
                }
 
-               // if we sent at least one argument, let's setup startindex
-               if (fn.nargs >= 1)
+               // They passed no arguments: simply duplicate the array
+               // and return the new one
+               if (fn.nargs < 1)
                {
-                       startindex = int(fn.arg(0).to_number());
-                       // if the index is negative, it means "places from the 
end" where -1 is the last element
-                       if (startindex < 0) startindex = startindex + 
array->elements.size();
-                       // if it's still negative, this is a problem
-                       if (startindex < 0 || startindex > 
int(array->elements.size()))
+                       as_array_object* newarray = new as_array_object(*array);
+                       fn.result->set_as_object(newarray);
+                       return;
+               }
+
+
+               startindex = int(fn.arg(0).to_number());
+
+               // if the index is negative, it means "places from the end"
+               // where -1 is the last element
+               if (startindex < 0) startindex = startindex + array->size();
+               // if it's still negative, this is a problem
+               if (startindex < 0 || (unsigned int)startindex > array->size())
+               {
+                       IF_VERBOSE_ACTION(log_error("bad startindex sent to 
array_slice! startindex: %s, Length: %zd",
+                               fn.arg(0).to_string(),array->size()));
+                       return;                         
+               }
+               // if we sent at least two arguments, setup endindex
+               if (fn.nargs >= 2)
+               {
+                       endindex = int(fn.arg(1).to_number());
+                       // if the index is negative, it means
+                       // "places from the end" where -1 is the last element
+                       if (endindex < 0) endindex = endindex + array->size();
+                       // the endindex is non-inclusive, so add 1
+                       endindex++;
+                       if (endindex < 0)
                        {
-                               IF_VERBOSE_ACTION(log_error("bad startindex 
sent to array_slice! startindex: %s, Length: %zd",
-                                       
fn.arg(0).to_string(),array->elements.size()));
+                               IF_VERBOSE_ACTION(log_error("bad endindex sent 
to array_slice! endindex: %s, length: %zd",
+                                       fn.arg(1).to_string(),array->size()));
                                return;                         
                        }
-                       // if we sent at least two arguments, setup endindex
-                       if (fn.nargs >= 2)
-                       {
-                               endindex = int(fn.arg(1).to_number());
-                               // if the index is negative, it means "places 
from the end" where -1 is the last element
-                               if (endindex < 0) endindex = endindex + 
array->elements.size();
-                               // the endindex is non-inclusive, so add 1
-                               endindex++;
-                               if (endindex < 0)
-                               {
-                                       IF_VERBOSE_ACTION(log_error("bad 
endindex sent to array_slice! endindex: %s, length: %zd",
-                                               
fn.arg(1).to_string(),array->elements.size()));
-                                       return;                         
-                               }
-                               // If they overshoot the end of the array, just 
copy to the end
-                               if (endindex > int(array->elements.size()) + 1) 
endindex = array->elements.size() + 1;
-                       }
-                       else
-                               // They didn't specify where to end, so choose 
the end of the array
-                               endindex = array->elements.size() + 1;
+                       // If they overshoot the end of the array,
+                       // just copy to the end
+                       if ((unsigned int)endindex > array->size() + 1)
+                               endindex = array->size() + 1;
                }
                else
                {
-                       // They passed no arguments: simply duplicate the array 
and return the new one
-                       as_array_object* newarray = new as_array_object;
-                       newarray->elements = array->elements;
-                       fn.result->set_as_object(newarray);
-                       return;
+                       // They didn't specify where to end, so choose the end 
of the array
+                       endindex = array->size() + 1;
                }
 
-               as_array_object* newarray = new as_array_object;
-
-               newarray->elements.resize(endindex - startindex - 1);
+               std::auto_ptr<as_array_object> newarray(array->slice(
+                       startindex, endindex));
 
-               for (int i=startindex;i<endindex;i++)
-                       newarray->elements[i-startindex] = array->elements[i];
+               fn.result->set_as_object(newarray.release());           
 
-               fn.result->set_as_object(newarray);             
        }
 
        // this sets all the callback members for an array function
         // it's called from as_array_object's constructor
        void array_init(as_array_object *array)
        {
-               array->set_member("length", &array_length);
+               // we don't need an explicit member here,
+               // we will be handling 'length' requests
+               // within overridden get_member()
+               //array->set_member("length", &array_length);
+
                array->set_member("join", &array_join);
                array->set_member("concat", &array_concat);
                array->set_member("slice", &array_slice);
@@ -373,6 +489,7 @@
                array->set_member("sortOn", &array_not_impl);
                array->set_member("reverse", &array_reverse);
                array->set_member("toString", &array_to_string);
+
                // TODO: These should be static members!
                array->set_member("CASEINSENSITIVE", 1);
                array->set_member("DESCENDING", 2);
Index: gnash/server/array.h
diff -u gnash/server/array.h:1.6 gnash/server/array.h:1.7
--- gnash/server/array.h:1.6    Wed Apr 26 22:10:09 2006
+++ gnash/server/array.h        Thu Apr 27 16:31:56 2006
@@ -41,28 +41,64 @@
 
 #include "action.h"
 #include <deque>
+#include <memory> // for auto_ptr
 
 namespace gnash {
 
-       struct as_array_object;
+       class as_array_object;
 
        void array_init(as_array_object *array);
 
-       struct as_array_object : public as_object
+       /// The Array ActionScript object
+       class as_array_object : public as_object
        {
-               std::deque<as_value> elements;
+       public:
+
                as_array_object();
 
-               const int size() const;
+               as_array_object(const as_array_object& other);
+
+               void push(as_value& val);
+
+               void unshift(as_value& val);
+
+               as_value shift();
+
+               as_value pop();
+
+               as_value at(unsigned int index);
+
+               void reverse();
+
+               std::string join(const std::string& separator);
+
+               std::string toString();
+
+               unsigned int size() const;
+
+               //void resize(unsigned int);
+
+               void concat(const as_array_object& other);
+
+               std::auto_ptr<as_array_object> slice(
+                       unsigned int start, unsigned int one_past_end);
+
+               /// Overridden to provide 'length' member
+               virtual bool get_member(const tu_stringi& name, as_value* val);
+
+               /// Overridden to provide array[#]=x semantic
+               virtual void set_member(const tu_stringi& name,
+                       const as_value& val );
+
+       private:
+
+               std::deque<as_value> elements;
 
                // this function is used internally by set_member and get_member
                // it takes a string that is the member name of the array and 
returns -1
                // if the string does not refer to an index, or an appropriate 
int if the string does refer to an index
                int index_requested(const tu_stringi& name);
 
-               virtual void set_member(const tu_stringi& name, const as_value& 
val );
-
-               virtual bool get_member(const tu_stringi& name, as_value *val);
        };
 
        void    array_new(const fn_call& fn);
Index: gnash/testsuite/actionscript.all/array.as
diff -u gnash/testsuite/actionscript.all/array.as:1.5 
gnash/testsuite/actionscript.all/array.as:1.6
--- gnash/testsuite/actionscript.all/array.as:1.5       Thu Apr 27 09:37:00 2006
+++ gnash/testsuite/actionscript.all/array.as   Thu Apr 27 16:31:56 2006
@@ -8,6 +8,7 @@
 #include "check.as"
 
 var a;
+var popped;
 a=[551,"asdf",12];
 b=[];
 b.push(551,"asdf",12);
@@ -20,7 +21,8 @@
 
 check_equals ( a.length, 3 );
 check_equals ( a[2], 12 );
-check_equals ( a.pop() , 12 );
+popped=a.pop();
+check_equals ( popped , 12 );
 check_equals ( a[2] , undefined );
 check_equals ( a[1] , "asdf" );
 a[1] = a[0];
@@ -62,11 +64,15 @@
 check_equals ( trysortarray.tostring() , 
"But,Different,alphabet,capitalization" );
 // TODO - test sort(Array.RETURNINDEXEDARRAY)
 
-check ( b.pop() == 12 );
-check ( b.pop() == "asdf" );
-check ( b.pop() == 551 );
+popped=b.pop();
+check ( popped == 12 );
+popped=b.pop();
+check ( popped == "asdf" );
+popped=b.pop();
+check ( popped == 551 );
 // make sure pops on an empty array don't cause problems
-check ( b.pop() == undefined );
+popped=b.pop();
+check ( popped == undefined );
 b.pop(); b.pop();
 check_equals ( b.length, 0 );
 b.unshift(8,2);
@@ -111,6 +117,17 @@
 check_equals ( c.length, 1001 );
 
 // $Log: array.as,v $
+// Revision 1.6  2006/04/27 16:31:56  strk
+//         * server/: (array.cpp, array.h): big cleanup, provided
+//         overrides for get_member() and set_member() to add support
+//         for the special 'length' element, turned array_as_object into
+//         a real class.
+//         * server/: (Object.cpp, Object.h): moved get_member
+//         and set_member to get_member_default and set_member_default
+//         with protected access level, provided public virtuals
+//         invoking the protected non-virtuals. This is to allow cleaner
+//         hooking for ActionScript classes.
+//
 // Revision 1.5  2006/04/27 09:37:00  strk
 // completed switch to check_equals() macro
 //




reply via email to

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