2
// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
4
// This program is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 3 of the License, or
7
// (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
#include "as_object.h" // for inheritance
22
#include "smart_ptr.h" // GNASH_USE_GC
26
#include <memory> // for auto_ptr
27
#include <boost/numeric/ublas/vector_sparse.hpp>
31
// Forward declarations
39
struct indexed_as_value : public as_value
43
indexed_as_value(const as_value& val, int index)
51
struct ContainerFiller {
53
ContainerFiller(T& c): cont(c) {}
54
void visit(as_value& v) { cont.push_back(v); }
59
/// The Array ActionScript object
60
class Array_as : public as_object
63
/// Other classes shouldn't care about this, but should rather use
64
/// the public iterator / const_iterator members.
65
typedef boost::numeric::ublas::mapped_vector<as_value> ArrayContainer;
69
typedef ArrayContainer::const_iterator const_iterator;
70
typedef ArrayContainer::iterator iterator;
72
typedef std::list<as_value> ValueList;
75
enum { itemBlank, itemValue };
77
/// Visit all elements
79
/// The visitor class will have to expose a visit(as_value&) method
81
template<class V> void visitAll(V& v)
83
// NOTE: we copy the elements as the visitor might call arbitrary code
84
// possibly modifying the container itself.
85
ArrayContainer copy = elements;
87
// iterating this way will skip holes
88
for (Array_as::iterator i=copy.begin(), ie=copy.end(); i!=ie; ++i)
92
// see dox in as_object.h
93
virtual void visitPropertyValues(AbstractPropertyVisitor& visitor) const;
95
// see dox in as_object.h
96
virtual void visitNonHiddenPropertyValues(AbstractPropertyVisitor& visitor) const;
101
/// Case-insensitive (z precedes A)
102
fCaseInsensitive = (1<<0), // 1
104
/// Descending order (b precedes a)
105
fDescending = (1<<1), // 2
107
/// If two or more elements in the array
108
/// have identical sort fields, return 0
109
/// and don't modify the array.
110
/// Otherwise proceed to sort the array.
111
fUniqueSort = (1<<2), // 4
113
/// Don't modify the array, rather return
114
/// a new array containing indexes into it
116
fReturnIndexedArray = (1<<3), // 8
118
/// Numerical sort (9 preceeds 10)
119
fNumeric = (1<<4) // 16
124
Array_as(const Array_as& other);
128
std::deque<indexed_as_value> get_indexed_elements();
130
Array_as::const_iterator begin();
132
Array_as::const_iterator end();
134
/// Push an element to the end of the array
137
/// The element to add
139
void push(const as_value& val);
141
void unshift(const as_value& val);
147
as_value at(unsigned int index) const;
149
Array_as* get_indices(std::deque<indexed_as_value> origElems);
153
void set_indexed(unsigned int index, const as_value &v);
156
/// If not-null will be used to properl invoke the toString()
157
/// method against member values.
159
std::string join(const std::string& separator, as_environment* env) const;
162
/// If not-null will be used to properly invoke the toString()
163
/// method against member values.
165
std::string toString(as_environment* env=NULL) const;
167
// override from as_object
168
std::string get_text_value() const
173
unsigned int size() const;
175
void resize(unsigned int);
177
void concat(const Array_as& other);
180
/// Return a newly created array containing elements
181
/// from 'start' up to but not including 'end'.
184
/// NOTE: assertions are:
186
/// assert(one_past_end >= start);
187
/// assert(one_past_end <= size());
188
/// assert(start <= size());
191
/// index to first element to include in result
194
/// @param one_past_end
195
/// index to one-past element to include in result
198
boost::intrusive_ptr<Array_as> slice(
199
unsigned int start, unsigned int one_past_end);
201
/// Remove first element matching the given value
203
/// Return true if any element was removed, false otherwise
205
/// NOTE: if an element is removed, holes in the array will be
209
/// The value to compare elements against
212
/// The environment to use when comparing (needed by as_value::equals)
214
bool removeFirst(const as_value& v);
217
/// Replace count elements from start with given values, optionally
218
/// returning the erased ones.
221
/// First element to remove. Will abort if invalid.
224
/// Number of elements to remove. Will abort if > then available.
227
/// If not null, use as a replacement for the cutted values
230
/// If not null, an array to push cutted values to.
232
void splice(unsigned int start, unsigned int count,
233
const std::vector<as_value>* replace=NULL,
234
Array_as* copy=NULL);
237
/// Sort the array, using given values comparator
240
/// boolean functor or function comparing two as_value& objects
242
template <class AVCMP>
247
// As for ISO/IEC 14882:2003 - 23.2.2.4.29
248
// the sort algorithm relies on the assumption
249
// that the comparator function implements
250
// a Strict Weak Ordering operator:
251
// http://www.sgi.com/tech/stl/StrictWeakOrdering.html
253
// Invalid comparator can lead to undefined behaviour,
254
// including invalid memory access and infinite loops.
256
// Pragmatically, it seems that std::list::sort is
257
// more robust in this reguard, so we'll sort a list
258
// instead of the queue. We want to sort a copy anyway
259
// to avoid the comparator changing the original container.
262
ContainerFiller<ValueList> filler(nelem);
265
size_t oldSize = elements.size(); // custom comparator might change input size
267
elements.resize(oldSize, false);
269
for (ValueList::iterator i=nelem.begin(), e=nelem.end(); i!=e; ++i)
271
elements[idx++] = *i;
276
/// Attempt to sort the array using given values comparator, avc.
277
/// If two or more elements in the array are equal, as determined
278
/// by the equality comparator ave, then the array is not sorted
279
/// and 0 is returned. Otherwise the array is sorted and returned.
282
/// boolean functor or function comparing two as_value& objects
283
/// used to determine sort-order
286
/// boolean functor or function comparing two as_value& objects
287
/// used to determine equality
289
template <class AVCMP, class AVEQ>
290
as_value sort(AVCMP avc, AVEQ ave)
294
// As for ISO/IEC 14882:2003 - 23.2.2.4.29
295
// the sort algorithm relies on the assumption
296
// that the comparator function implements
297
// a Strict Weak Ordering operator:
298
// http://www.sgi.com/tech/stl/StrictWeakOrdering.html
300
// Invalid comparator can lead to undefined behaviour,
301
// including invalid memory access and infinite loops.
303
// Pragmatically, it seems that std::list::sort is
304
// more robust in this reguard, so we'll sort a list
305
// instead of the queue. We want to sort a copy anyway
306
// to avoid the comparator changing the original container.
309
typedef std::list<as_value> ValueList;
311
ContainerFiller<ValueList> filler(nelem);
314
size_t oldSize = elements.size(); // custom comparator might change input size
318
if (std::adjacent_find(nelem.begin(), nelem.end(), ave) != nelem.end() )
321
elements.resize(oldSize, false);
323
for (ValueList::iterator i=nelem.begin(), e=nelem.end(); i!=e; ++i)
325
elements[idx++] = *i;
328
return as_value(this);
332
/// Return a new array containing sorted index of this array
335
/// boolean functor or function comparing two as_value& objects
337
template <class AVCMP>
338
Array_as* sort_indexed(AVCMP avc)
340
std::deque<indexed_as_value> ielem = get_indexed_elements();
341
std::sort(ielem.begin(), ielem.end(), avc);
342
return get_indices(ielem);
346
/// Return a new array containing sorted index of this array.
347
/// If two or more elements in the array are equal, as determined
348
/// by the equality comparator ave, then 0 is returned instead.
351
/// boolean functor or function comparing two as_value& objects
352
/// used to determine sort-order
355
/// boolean functor or function comparing two as_value& objects
356
/// used to determine equality
358
template <class AVCMP, class AVEQ>
359
as_value sort_indexed(AVCMP avc, AVEQ ave)
361
std::deque<indexed_as_value> ielem = get_indexed_elements();
363
std::sort(ielem.begin(), ielem.end(), avc);
365
if (std::adjacent_find(ielem.begin(), ielem.end(), ave) != ielem.end() )
368
return get_indices(ielem);
371
/// Why is this overridden?
372
virtual bool get_member(string_table::key name, as_value* val,
373
string_table::key nsname = 0);
375
/// Overridden to provide array[#]=x semantic
376
virtual bool set_member(string_table::key name,
377
const as_value& val, string_table::key nsname=0, bool ifFound=false);
379
/// Overridden to deal with indexed elements
380
virtual std::pair<bool,bool> delProperty(string_table::key name, string_table::key nsname = 0);
382
/// Overridden to expose indexed elements
383
virtual bool hasOwnProperty(string_table::key name, string_table::key nsname = 0);
385
/// Enumerate elements
387
/// See as_object::enumerateNonProperties(as_environment&) for more info.
389
virtual void enumerateNonProperties(as_environment&) const;
394
/// Mark array-specific reachable resources and invoke
395
/// the parent's class version (markAsObjectReachable)
397
/// array-specific reachable resources are:
398
/// - The elements values (elements)
400
virtual void markReachableResources() const;
401
#endif // GNASH_USE_GC
405
ArrayContainer elements;
407
// this function is used internally by set_member and get_member
408
// it takes a string that is the member name of the array and returns -1
409
// if the string does not refer to an index, or an appropriate int if the string does refer to an index
410
int index_requested(string_table::key name);
412
/// Shift all elements to the left by count positions
414
/// Pre-condition: size of the array must be >= count
415
/// Post-condition: size of the array will reduce by 'count'
417
void shiftElementsLeft(unsigned int count);
419
/// Shift all elements to the right by count positions
421
/// Pre-condition: none
422
/// Post-condition: size of the array will incremented by 'count'
424
void shiftElementsRight(unsigned int count);
428
/// Initialize the global.Array object
429
// needed by SWFHandlers::ActionInitArray
430
void array_class_init(as_object& global);
432
/// Constructor for ActionScript class Array.
433
// needed by SWFHandlers::ActionInitArray
434
as_value array_new(const fn_call& fn);