1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2006
21 * the Initial Developer. All Rights Reserved.
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 #ifndef __avmplus_VectorClass_impl__
42 #define __avmplus_VectorClass_impl__
46 // ----------------------------
48 Atom
TypedVectorClassBase::call(int argc
, Atom
* argv
)
50 Toplevel
* toplevel
= this->toplevel();
51 AvmCore
* core
= toplevel
->core();
54 toplevel
->throwArgumentError(kCoerceArgumentCountError
, core
->toErrorString(argc
));
56 Traits
* itraits
= ivtable()->traits
;
57 if (AvmCore::istype(argv
[1], itraits
))
60 if (!AvmCore::isObject(argv
[1]))
61 toplevel
->throwTypeError(kCheckTypeFailedError
, core
->atomToErrorString(argv
[1]), core
->toErrorString(itraits
));
63 ScriptObject
* so_args
= AvmCore::atomToScriptObject(argv
[1]);
64 uint32_t len
= so_args
->getLengthProperty();
65 return createAndInitVectorFromObject(so_args
, len
);
68 void TypedVectorClassBase::_forEach(Atom thisAtom
, ScriptObject
* callback
, Atom thisObject
)
70 return ArrayClass::generic_forEach(toplevel(), thisAtom
, callback
, thisObject
);
73 bool TypedVectorClassBase::_every(Atom thisAtom
, ScriptObject
* callback
, Atom thisObject
)
75 return ArrayClass::generic_every(toplevel(), thisAtom
, callback
, thisObject
);
78 bool TypedVectorClassBase::_some(Atom thisAtom
, ScriptObject
* callback
, Atom thisObject
)
80 return ArrayClass::generic_some(toplevel(), thisAtom
, callback
, thisObject
);
83 Atom
TypedVectorClassBase::_sort(Atom thisAtom
, ArrayObject
* args
)
85 return ArrayClass::generic_sort(toplevel(), thisAtom
, args
);
88 // ----------------------------
91 TypedVectorClass
<OBJ
>::TypedVectorClass(VTable
* vtable
)
92 : TypedVectorClassBase(vtable
)
94 setPrototypePtr(toplevel()->objectClass
->construct());
98 OBJ
* TypedVectorClass
<OBJ
>::newVector(uint32_t length
, bool fixed
)
100 OBJ
* v
= (OBJ
*)OBJ::create(gc(), ivtable(), prototypePtr());
101 v
->m_vecClass
= this;
103 v
->set_length(length
);
109 Atom TypedVectorClass
<OBJ
>::createAndInitVectorFromObject(ScriptObject
* so_args
, uint32_t len
)
111 OBJ
* v
= newVector();
112 v
->_spliceHelper_so(0, len
, 0, so_args
, 0);
117 Atom TypedVectorClass
<OBJ
>::constructImpl(int argc
, Atom
* argv
)
123 len
= AvmCore::toUInt32(argv
[1]);
126 fixed
= AvmCore::boolean(argv
[2]) != 0;
129 vtable
->init
->argcError(argc
);
133 OBJ
* v
= newVector(len
, fixed
);
137 // ----------------------------
139 VectorBaseObject::VectorBaseObject(VTable
* ivtable
, ScriptObject
* delegate
)
140 : ScriptObject(ivtable
, delegate
)
146 VectorBaseObject
* VectorBaseObject::_newVector()
148 AvmAssert(m_vecClass
!= NULL
);
149 Atom args
[1] = { nullObjectAtom
};
150 return (VectorBaseObject
*)AvmCore::atomToScriptObject(m_vecClass
->construct(0, args
));
153 void FASTCALL
VectorBaseObject::throwFixedError() const
155 toplevel()->throwRangeError(kVectorFixedError
);
158 Atom
VectorBaseObject::_mapImpl(ScriptObject
* callback
, Atom thisObject
, VectorBaseObject
* r
, uint32_t len
)
160 AvmCore
* core
= this->core();
163 ScriptObject
* d
= this;
164 for (uint32_t i
= 0; i
< len
; i
++)
166 // If thisObject is null, the call function will substitute the global object
167 // args are modified in place by callee
170 d
->getUintProperty(i
), // element
171 core
->uintToAtom(i
), // index
174 Atom result
= callback
->call(3, args
);
175 r
->setUintProperty(i
, result
);
181 Atom
VectorBaseObject::_filterImpl(ScriptObject
* callback
, Atom thisObject
, VectorBaseObject
* r
, uint32_t len
)
183 AvmCore
* core
= this->core();
186 ScriptObject
* d
= this;
187 for (uint32_t i
= 0, k
= 0; i
< len
; i
++)
189 // If thisObject is null, the call function will substitute the global object
190 // args are modified in place by callee
191 Atom element
= d
->getUintProperty(i
);
195 core
->uintToAtom(i
), // index
198 Atom result
= callback
->call(3, args
);
199 if (result
== trueAtom
)
200 r
->setUintProperty(k
++, element
);
206 // ----------------------------
208 template<class TLIST
>
209 TypedVectorObject
<TLIST
>::TypedVectorObject(VTable
* ivtable
, ScriptObject
* delegate
)
210 : VectorBaseObject(ivtable
, delegate
)
211 , m_list(ivtable
->gc(), 0)
215 template<class TLIST
>
216 bool TypedVectorObject
<TLIST
>::hasAtomProperty(Atom name
) const
219 VectorIndexStatus status
= getVectorIndex(name
, index
);
220 if (status
== kValidNumber
)
222 return index
< m_list
.length();
224 else if (status
== kInvalidNumber
)
228 else // status == kNotNumber
230 return ScriptObject::hasAtomProperty(name
);
234 template<class TLIST
>
235 void TypedVectorObject
<TLIST
>::setAtomProperty(Atom name
, Atom value
)
238 VectorIndexStatus status
= getVectorIndex(name
, index
);
239 if (status
== kValidNumber
)
241 setUintProperty(index
, value
);
245 toplevel()->throwReferenceError(kWriteSealedError
, core()->string(name
), traits());
249 template<class TLIST
>
250 Atom TypedVectorObject
<TLIST
>::getAtomProperty(Atom name
) const
253 VectorIndexStatus status
= getVectorIndex(name
, index
);
254 if (status
== kValidNumber
)
256 return getUintProperty(index
);
258 else if (status
== kInvalidNumber
)
260 // Not a valid indexed name - has a decimal part
261 toplevel()->throwReferenceError(kReadSealedError
, core()->string(name
), traits());
262 return undefinedAtom
; // not reached
264 else // status == kNotNumber
266 // Check the prototype chain - that will throw if there is no match
267 return getAtomPropertyFromProtoChain(name
, getDelegate(), traits());
271 template<class TLIST
>
272 /*virtual*/ uint32_t TypedVectorObject
<TLIST
>::getLength() const
277 template<class TLIST
>
278 /*virtual*/ void TypedVectorObject
<TLIST
>::setLength(uint32_t length
)
283 template<class TLIST
>
284 void TypedVectorObject
<TLIST
>::set_length(uint32_t newLength
)
287 // this is what the old code did, so we'll do it too: set the capacity explicitly if we grow
288 if (newLength
> m_list
.capacity())
290 m_list
.set_capacity(newLength
);
292 m_list
.set_length(newLength
);
295 template<class TLIST
>
296 Atom TypedVectorObject
<TLIST
>::nextName(int index
)
298 AvmAssert(index
> 0);
299 if (uint32_t(index
) <= m_list
.length())
301 return core()->intToAtom(index
-1);
305 return nullStringAtom
;
309 template<class TLIST
>
310 Atom TypedVectorObject
<TLIST
>::nextValue(int index
)
312 AvmAssert(index
> 0);
313 if (uint32_t(index
) <= m_list
.length())
315 return getUintProperty(index
-1);
319 return undefinedAtom
;
323 template<class TLIST
>
324 int TypedVectorObject
<TLIST
>::nextNameIndex(int index
)
326 if (uint32_t(index
) < m_list
.length())
336 template<class TLIST
>
337 Atom TypedVectorObject
<TLIST
>::_map(ScriptObject
* callback
, Atom thisObject
)
339 TypedVectorObject
<TLIST
>* r
= (TypedVectorObject
<TLIST
>*)_newVector();
340 uint32_t const len
= m_list
.length();
342 return _mapImpl(callback
, thisObject
, r
, len
);
345 template<class TLIST
>
346 Atom TypedVectorObject
<TLIST
>::_filter(ScriptObject
* callback
, Atom thisObject
)
348 TypedVectorObject
<TLIST
>* r
= (TypedVectorObject
<TLIST
>*)_newVector();
349 uint32_t const len
= m_list
.length();
350 return _filterImpl(callback
, thisObject
, r
, len
);
353 template<class TLIST
>
354 void TypedVectorObject
<TLIST
>::_spliceHelper_so(uint32_t insertPoint
, uint32_t insertCount
, uint32_t deleteCount
, ScriptObject
* so_args
, uint32_t offset
)
356 AvmAssert(!AvmCore::istype(so_args
->atom(), vtable
->traits
));
358 // NB: so_args could be any kind of object, but in practice,
359 // it's almost always an ArrayObject; it might be profitable
360 // to sniff for that case and optimize appropriately.
362 // passing NULL for args inserts the proper space, but leaves the inserted entries empty
363 m_list
.splice(insertPoint
, insertCount
, deleteCount
, NULL
);
364 for (uint32_t i
= 0; i
< insertCount
; i
++)
366 typename
TLIST::OPAQUE_TYPE value
;
367 atomToValue(so_args
->getUintProperty(i
+offset
), value
);
368 m_list
.set(insertPoint
+i
, (typename
TLIST::TYPE
)value
);
372 template<class TLIST
>
373 void TypedVectorObject
<TLIST
>::_spliceHelper(uint32_t insertPoint
, uint32_t insertCount
, uint32_t deleteCount
, Atom args
, uint32_t offset
)
375 if (AvmCore::istype(args
, vtable
->traits
))
377 TypedVectorObject
<TLIST
>* vec_args
= (TypedVectorObject
<TLIST
>*)AvmCore::atomToScriptObject(args
);
378 m_list
.splice(insertPoint
, insertCount
, deleteCount
, vec_args
->m_list
, offset
);
380 else if (AvmCore::isObject(args
))
382 ScriptObject
* so_args
= AvmCore::atomToScriptObject(args
);
383 _spliceHelper_so(insertPoint
, insertCount
, deleteCount
, so_args
, offset
);
387 AvmAssert(insertCount
== 0);
388 m_list
.splice(insertPoint
, 0, deleteCount
, NULL
);
392 template<class TLIST
>
393 void TypedVectorObject
<TLIST
>::_splice(uint32_t insertPoint
, uint32_t insertCount
, uint32_t deleteCount
, const Atom
* argv
)
395 // passing NULL for args inserts the proper space, but leaves the inserted entries empty
396 m_list
.splice(insertPoint
, insertCount
, deleteCount
, NULL
);
397 for (uint32_t i
= 0; i
< insertCount
; i
++)
399 typename
TLIST::OPAQUE_TYPE value
;
400 atomToValue(argv
[i
], value
);
401 m_list
.set(insertPoint
+i
, (typename
TLIST::TYPE
)value
);
405 template<class TLIST
>
406 uint32_t TypedVectorObject
<TLIST
>::AS3_push(Atom
* argv
, int argc
)
409 _splice(m_list
.length(), argc
, 0, argv
);
410 return m_list
.length();
413 template<class TLIST
>
414 typename
TLIST::TYPE TypedVectorObject
<TLIST
>::AS3_pop()
417 return m_list
.isEmpty() ?
418 (typename
TLIST::TYPE
)TypedVectorConstants
<typename
TLIST::OPAQUE_TYPE
>::undefinedValue() :
422 template<class TLIST
>
423 typename
TLIST::TYPE TypedVectorObject
<TLIST
>::AS3_shift()
426 return m_list
.isEmpty() ?
427 (typename
TLIST::TYPE
)TypedVectorConstants
<typename
TLIST::OPAQUE_TYPE
>::undefinedValue() :
428 m_list
.removeFirst();
431 template<class TLIST
>
432 uint32_t TypedVectorObject
<TLIST
>::AS3_unshift(Atom
* argv
, int argc
)
435 _splice(0, argc
, 0, argv
);
436 return m_list
.length();
439 template<class TLIST
>
440 typename
TLIST::TYPE TypedVectorObject
<TLIST
>::_getNativeIntProperty(int32_t index_i
) const
442 // Implicitly convert negative values to large uints, which will always be > length
443 uint32_t const index
= checkReadIndex_u(uint32_t(index_i
));
444 return m_list
.get(index
);
447 template<class TLIST
>
448 void TypedVectorObject
<TLIST
>::_setNativeIntProperty(int32_t index_i
, typename
TLIST::TYPE value
)
450 // Implicitly convert negative values to large uints, which will always be > length
451 uint32_t const index
= checkWriteIndex_u(uint32_t(index_i
));
452 m_list
.set(index
, value
);
455 template<class TLIST
>
456 typename
TLIST::TYPE TypedVectorObject
<TLIST
>::_getNativeUintProperty(uint32_t index
) const
458 index
= checkReadIndex_u(index
);
459 return m_list
.get(index
);
462 template<class TLIST
>
463 void TypedVectorObject
<TLIST
>::_setNativeUintProperty(uint32_t index
, typename
TLIST::TYPE value
)
465 index
= checkWriteIndex_u(index
);
466 m_list
.set(index
, value
);
469 template<class TLIST
>
470 bool TypedVectorObject
<TLIST
>::_hasUintProperty(uint32_t index
) const
472 return (index
< m_list
.length());
475 template<class TLIST
>
476 Atom TypedVectorObject
<TLIST
>::_getUintProperty(uint32_t index
) const
478 index
= checkReadIndex_u(index
);
479 return valueToAtom((typename
TLIST::OPAQUE_TYPE
)m_list
.get(index
));
482 template<class TLIST
>
483 void TypedVectorObject
<TLIST
>::_setUintProperty(uint32_t index
, Atom value
)
485 index
= checkWriteIndex_u(index
);
486 typename
TLIST::OPAQUE_TYPE tmp
;
487 atomToValue(value
, tmp
);
488 m_list
.set(index
, (typename
TLIST::TYPE
)tmp
);
491 template<class TLIST
>
492 Atom TypedVectorObject
<TLIST
>::_getIntProperty(int32_t index_i
) const
494 // Implicitly convert negative values to large uints, which will always be > length
495 uint32_t const index
= uint32_t(index_i
);
496 return _getUintProperty(index
);
499 template<class TLIST
>
500 void TypedVectorObject
<TLIST
>::_setIntProperty(int32_t index_i
, Atom value
)
502 // Implicitly convert negative values to large uints, which will always be > length
503 uint32_t const index
= uint32_t(index_i
);
504 _setUintProperty(uint32_t(index
), value
);
507 template<class TLIST
>
508 void FASTCALL TypedVectorObject
<TLIST
>::throwRangeError(uint32_t index
) const
510 toplevel()->throwRangeError(kOutOfRangeError
, core()->uintToString(index
), core()->uintToString(m_list
.length()));
513 // ----------------------------
514 // ----------------------------
515 // ----------------------------
519 #endif /* __avmplus_VectorClass_impl__ */