array_object.cpp
来自「将konqueror浏览器移植到ARM9 2410中」· C++ 代码 · 共 342 行
CPP
342 行
/* * This file is part of the KDE libraries * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "kjs.h"#include "operations.h"#include "types.h"#include "array_object.h"#include <stdio.h>using namespace KJS;ArrayObject::ArrayObject(const Object &funcProto, const Object &arrayProto) : ConstructorImp(funcProto, 1){ // ECMA 15.4.3.1 Array.prototype setPrototypeProperty(arrayProto);}// ECMA 15.6.1Completion ArrayObject::execute(const List &args){ // equivalent to 'new Array(....)' KJSO result = construct(args); return Completion(ReturnValue, result);}// ECMA 15.6.2Object ArrayObject::construct(const List &args){ Object result = Object::create(ArrayClass); unsigned int len; ListIterator it = args.begin(); // a single argument might denote the array size if (args.size() == 1 && it->isA(NumberType)) len = it->toUInt32(); else { // initialize array len = args.size(); for (unsigned int u = 0; it != args.end(); it++, u++) result.put(UString::from(u), *it); } // array size result.put("length", len, DontEnum | DontDelete); return result;}// ECMA 15.6.4ArrayPrototype::ArrayPrototype(const Object& proto) : ObjectImp(ArrayClass, Null(), proto){ // The constructor will be added later in ArrayObject's constructor put("length", 0u, DontEnum | DontDelete);}KJSO ArrayPrototype::get(const UString &p) const{ int id; if(p == "toString") id = ArrayProtoFunc::ToString; else if(p == "toLocaleString") id = ArrayProtoFunc::ToLocaleString; else if(p == "concat") id = ArrayProtoFunc::Concat; else if (p == "join") id = ArrayProtoFunc::Join; else if(p == "pop") id = ArrayProtoFunc::Pop; else if(p == "push") id = ArrayProtoFunc::Push; else if(p == "reverse") id = ArrayProtoFunc::Reverse; else if(p == "shift") id = ArrayProtoFunc::Shift; else if(p == "slice") id = ArrayProtoFunc::Slice; else if(p == "sort") id = ArrayProtoFunc::Sort; else if(p == "splice") id = ArrayProtoFunc::Splice; else if(p == "unshift") id = ArrayProtoFunc::UnShift; else return Imp::get(p); return Function(new ArrayProtoFunc(id));}// ECMA 15.4.4Completion ArrayProtoFunc::execute(const List &args){ KJSO result, obj, obj2; Object thisObj = Object::dynamicCast(thisValue()); unsigned int length = thisObj.get("length").toUInt32(); unsigned int middle; UString str = "", str2; UString separator = ","; switch (id) { case ToLocaleString: /* TODO */ // fall trough case ToString: if (!thisObj.getClass() == ArrayClass) { result = Error::create(TypeError); break; } // fall trough case Join: { if (!args[0].isA(UndefinedType)) separator = args[0].toString().value(); for (unsigned int k = 0; k < length; k++) { if (k >= 1) str += separator; obj = thisObj.get(UString::from(k)); if (!obj.isA(UndefinedType) && !obj.isA(NullType)) str += obj.toString().value(); } } result = String(str); break; case Concat: { result = Object::create(ArrayClass); int n = 0; obj = thisObj; ListIterator it = args.begin(); for (;;) { if (obj.isA(ObjectType) && static_cast<Object&>(obj).getClass() == ArrayClass) { unsigned int k = 0; if (n > 0) length = obj.get("length").toUInt32(); while (k < length) { UString p = UString::from(k); if (obj.hasProperty(p)) result.put(UString::from(n), obj.get(p)); n++; k++; } } else { result.put(UString::from(n), obj); n++; } if (it == args.end()) break; obj = it++; } result.put("length", Number(n), DontEnum | DontDelete); } break; case Pop: if (length == 0) { thisObj.put("length", Number(length), DontEnum | DontDelete); result = Undefined(); } else { str = UString::from(length - 1); result = thisObj.get(str); thisObj.deleteProperty(str); thisObj.put("length", length - 1, DontEnum | DontDelete); } break; case Push: { for (int n = 0; n < args.size(); n++) thisObj.put(UString::from(length + n), args[n]); length += args.size(); thisObj.put("length", length, DontEnum | DontDelete); result = Number(length); } break; case Reverse: { middle = length / 2; for (unsigned int k = 0; k < middle; k++) { str = UString::from(k); str2 = UString::from(length - k - 1); obj = thisObj.get(str); obj2 = thisObj.get(str2); if (thisObj.hasProperty(str2)) { if (thisObj.hasProperty(str)) { thisObj.put(str, obj2); thisObj.put(str2, obj); } else { thisObj.put(str, obj2); thisObj.deleteProperty(str2); } } else { if (thisObj.hasProperty(str)) { thisObj.deleteProperty(str); thisObj.put(str2, obj); } else { // why delete something that's not there ? Strange. thisObj.deleteProperty(str); thisObj.deleteProperty(str2); } } } } result = thisObj; break; case Shift: if (length == 0) { thisObj.put("length", Number(length), DontEnum | DontDelete); result = Undefined(); } else { result = thisObj.get("0"); for(unsigned int k = 1; k < length; k++) { str = UString::from(k); str2 = UString::from(k-1); if (thisObj.hasProperty(str)) { obj = thisObj.get(str); thisObj.put(str2, obj); } else thisObj.deleteProperty(str2); } thisObj.deleteProperty(UString::from(length - 1)); thisObj.put("length", length - 1, DontEnum | DontDelete); } break; case Slice: // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 { result = Object::create(ArrayClass); // We return a new array int begin = args[0].toUInt32(); int end = length; if (!args[1].isA(UndefinedType)) { end = args[1].toUInt32(); if ( end < 0 ) end += length; } // safety tests if ( begin < 0 || end < 0 || begin >= end ) { result.put("length", Number(0), DontEnum | DontDelete); break; } //printf( "Slicing from %d to %d \n", begin, end ); for(unsigned int k = 0; k < (unsigned int) end-begin; k++) { str = UString::from(k+begin); str2 = UString::from(k); if (thisObj.hasProperty(str)) { obj = thisObj.get(str); result.put(str2, obj); } } result.put("length", end - begin, DontEnum | DontDelete); break; } case Sort: {#if 0 printf("KJS Array::Sort length=%d\n", length); for ( unsigned int i = 0 ; i<length ; ++i ) printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(UString::from(i)).toString().value().ascii() );#endif Object sortFunction; bool useSortFunction = !args[0].isA(UndefinedType); if (useSortFunction) { sortFunction = args[0].toObject(); if (!sortFunction.implementsCall()) useSortFunction = false; } if (length == 0) { thisObj.put("length", Number(0), DontEnum | DontDelete); result = Undefined(); break; } // "Min" sort. Not the fastest, but definitely less code than heapsort // or quicksort, and much less swapping than bubblesort/insertionsort. for ( unsigned int i = 0 ; i<length-1 ; ++i ) { KJSO iObj = thisObj.get(UString::from(i)); unsigned int themin = i; KJSO minObj = iObj; for ( unsigned int j = i+1 ; j<length ; ++j ) { KJSO jObj = thisObj.get(UString::from(j)); int cmp; if ( useSortFunction ) { List l; l.append(jObj); l.append(minObj); cmp = sortFunction.executeCall( Global::current(), &l ).toInt32(); } else cmp = ( jObj.toString().value() < minObj.toString().value() ) ? -1 : 1; if ( cmp < 0 ) { themin = j; minObj = jObj; } } // Swap themin and i if ( themin > i ) { //printf("KJS Array::Sort: swapping %d and %d\n", i, themin ); thisObj.put( UString::from(i), minObj ); thisObj.put( UString::from(themin), iObj ); } }#if 0 printf("KJS Array::Sort -- Resulting array:\n"); for ( unsigned int i = 0 ; i<length ; ++i ) printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(UString::from(i)).toString().value().ascii() );#endif result = thisObj; break; } // TODO Splice // TODO Unshift default: result = Undefined(); } return Completion(ReturnValue, result);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?