⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 array_object.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// -*- c-basic-offset: 2 -*-/* *  This file is part of the KDE libraries *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org) *  Copyright (C) 2003 Apple Computer, Inc. * *  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 "value.h"#include "object.h"#include "types.h"#include "interpreter.h"#include "operations.h"#include "array_object.h"#include "internal.h"#include "error_object.h"#include "array_object.lut.h"#include <stdio.h>#include <assert.h>using namespace KJS;// ------------------------------ ArrayInstanceImp -----------------------------const unsigned sparseArrayCutoff = 10000;const ClassInfo ArrayInstanceImp::info = {"Array", 0, 0, 0};ArrayInstanceImp::ArrayInstanceImp(ObjectImp *proto, unsigned initialLength)  : ObjectImp(proto)  , length(initialLength)  , storageLength(initialLength < sparseArrayCutoff ? initialLength : 0)  , capacity(storageLength)  , storage(capacity ? (ValueImp **)calloc(capacity, sizeof(ValueImp *)) : 0){}ArrayInstanceImp::ArrayInstanceImp(ObjectImp *proto, const List &list)  : ObjectImp(proto)  , length(list.size())  , storageLength(length)  , capacity(storageLength)  , storage(capacity ? (ValueImp **)malloc(sizeof(ValueImp *) * capacity) : 0){  ListIterator it = list.begin();  unsigned l = length;  for (unsigned i = 0; i < l; ++i) {    storage[i] = (it++).imp();  }}ArrayInstanceImp::~ArrayInstanceImp(){  free(storage);}Value ArrayInstanceImp::get(ExecState *exec, const Identifier &propertyName) const{  if (propertyName == lengthPropertyName)    return Number(length);  bool ok;  unsigned index = propertyName.toArrayIndex(&ok);  if (ok) {    if (index >= length)      return Undefined();    if (index < storageLength) {      ValueImp *v = storage[index];      return v ? Value(v) : Undefined();    }  }  return ObjectImp::get(exec, propertyName);}Value ArrayInstanceImp::get(ExecState *exec, unsigned index) const{  if (index >= length)    return Undefined();  if (index < storageLength) {    ValueImp *v = storage[index];    return v ? Value(v) : Undefined();  }    return ObjectImp::get(exec, Identifier::from(index));}// Special implementation of [[Put]] - see ECMA 15.4.5.1void ArrayInstanceImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr){  if (propertyName == lengthPropertyName) {    setLength(value.toUInt32(exec), exec);    return;  }    bool ok;  unsigned index = propertyName.toArrayIndex(&ok);  if (ok) {    put(exec, index, value, attr);    return;  }    ObjectImp::put(exec, propertyName, value, attr);}void ArrayInstanceImp::put(ExecState *exec, unsigned index, const Value &value, int attr){  if (index < sparseArrayCutoff && index >= storageLength) {    resizeStorage(index + 1);  }  if (index >= length) {    length = index + 1;  }  if (index < storageLength) {    storage[index] = value.imp();    return;  }    assert(index >= sparseArrayCutoff);  ObjectImp::put(exec, Identifier::from(index), value, attr);}bool ArrayInstanceImp::hasProperty(ExecState *exec, const Identifier &propertyName) const{  if (propertyName == lengthPropertyName)    return true;    bool ok;  unsigned index = propertyName.toArrayIndex(&ok);  if (ok) {    if (index >= length)      return false;    if (index < storageLength) {      ValueImp *v = storage[index];      return v && v != UndefinedImp::staticUndefined;    }  }    return ObjectImp::hasProperty(exec, propertyName);}bool ArrayInstanceImp::hasProperty(ExecState *exec, unsigned index) const{  if (index >= length)    return false;  if (index < storageLength) {    ValueImp *v = storage[index];    return v && v != UndefinedImp::staticUndefined;  }    return ObjectImp::hasProperty(exec, Identifier::from(index));}bool ArrayInstanceImp::deleteProperty(ExecState *exec, const Identifier &propertyName){  if (propertyName == lengthPropertyName)    return false;    bool ok;  uint32_t index = propertyName.toUInt32(&ok);  if (ok) {    if (index >= length)      return true;    if (index < storageLength) {      storage[index] = 0;      return true;    }  }    return ObjectImp::deleteProperty(exec, propertyName);}bool ArrayInstanceImp::deleteProperty(ExecState *exec, unsigned index){  if (index >= length)    return true;  if (index < storageLength) {    storage[index] = 0;    return true;  }    return ObjectImp::deleteProperty(exec, Identifier::from(index));}ReferenceList ArrayInstanceImp::propList(ExecState *exec, bool recursive){  ReferenceList properties = ObjectImp::propList(exec,recursive);  // avoid fetching this every time through the loop  ValueImp *undefined = UndefinedImp::staticUndefined;  for (unsigned i = 0; i < storageLength; ++i) {    ValueImp *imp = storage[i];    if (imp && imp != undefined) {      properties.append(Reference(this, i));    }  }  return properties;}void ArrayInstanceImp::resizeStorage(unsigned newLength){    if (newLength < storageLength) {      memset(storage + newLength, 0, sizeof(ValueImp *) * (storageLength - newLength));    }    if (newLength > capacity) {      unsigned newCapacity;      if (newLength > sparseArrayCutoff) {        newCapacity = newLength;      } else {        newCapacity = (newLength * 3 + 1) / 2;        if (newCapacity > sparseArrayCutoff) {          newCapacity = sparseArrayCutoff;        }      }      storage = (ValueImp **)realloc(storage, newCapacity * sizeof (ValueImp *));      memset(storage + capacity, 0, sizeof(ValueImp *) * (newCapacity - capacity));      capacity = newCapacity;    }    storageLength = newLength;}void ArrayInstanceImp::setLength(unsigned newLength, ExecState *exec){  if (newLength <= storageLength) {    resizeStorage(newLength);  }  if (newLength < length) {    ReferenceList sparseProperties;        _prop.addSparseArrayPropertiesToReferenceList(sparseProperties, Object(this));        ReferenceListIterator it = sparseProperties.begin();    while (it != sparseProperties.end()) {      Reference ref = it++;      bool ok;      unsigned index = ref.getPropertyName(exec).toArrayIndex(&ok);      if (ok && index > newLength) {	ref.deleteValue(exec);      }    }  }    length = newLength;}void ArrayInstanceImp::mark(){  ObjectImp::mark();  unsigned l = storageLength;  for (unsigned i = 0; i < l; ++i) {    ValueImp *imp = storage[i];    if (imp && !imp->marked())      imp->mark();  }}static ExecState *execForCompareByStringForQSort;static int compareByStringForQSort(const void *a, const void *b){    ExecState *exec = execForCompareByStringForQSort;    ValueImp *va = *(ValueImp **)a;    ValueImp *vb = *(ValueImp **)b;    if (va->dispatchType() == UndefinedType) {        return vb->dispatchType() == UndefinedType ? 0 : 1;    }    if (vb->dispatchType() == UndefinedType) {        return -1;    }    return compare(va->dispatchToString(exec), vb->dispatchToString(exec));}void ArrayInstanceImp::sort(ExecState *exec){    int lengthNotIncludingUndefined = pushUndefinedObjectsToEnd(exec);        execForCompareByStringForQSort = exec;    qsort(storage, lengthNotIncludingUndefined, sizeof(ValueImp *), compareByStringForQSort);    execForCompareByStringForQSort = 0;}struct CompareWithCompareFunctionArguments {    CompareWithCompareFunctionArguments(ExecState *e, ObjectImp *cf)        : exec(e)        , compareFunction(cf)        , globalObject(e->dynamicInterpreter()->globalObject())    {        arguments.append(Undefined());        arguments.append(Undefined());    }    ExecState *exec;    ObjectImp *compareFunction;    List arguments;    Object globalObject;};static CompareWithCompareFunctionArguments *compareWithCompareFunctionArguments;static int compareWithCompareFunctionForQSort(const void *a, const void *b){    CompareWithCompareFunctionArguments *args = compareWithCompareFunctionArguments;    ValueImp *va = *(ValueImp **)a;    ValueImp *vb = *(ValueImp **)b;    if (va->dispatchType() == UndefinedType) {        return vb->dispatchType() == UndefinedType ? 0 : 1;    }    if (vb->dispatchType() == UndefinedType) {        return -1;    }    args->arguments.clear();    args->arguments.append(va);    args->arguments.append(vb);    double compareResult = args->compareFunction->call        (args->exec, args->globalObject, args->arguments).toNumber(args->exec);    return compareResult < 0 ? -1 : compareResult > 0 ? 1 : 0;}void ArrayInstanceImp::sort(ExecState *exec, Object &compareFunction){    int lengthNotIncludingUndefined = pushUndefinedObjectsToEnd(exec);        CompareWithCompareFunctionArguments args(exec, compareFunction.imp());    compareWithCompareFunctionArguments = &args;    qsort(storage, lengthNotIncludingUndefined, sizeof(ValueImp *), compareWithCompareFunctionForQSort);    compareWithCompareFunctionArguments = 0;}unsigned ArrayInstanceImp::pushUndefinedObjectsToEnd(ExecState *exec){    ValueImp *undefined = UndefinedImp::staticUndefined;    unsigned o = 0;        for (unsigned i = 0; i != storageLength; ++i) {        ValueImp *v = storage[i];        if (v && v != undefined) {            if (o != i)                storage[o] = v;            o++;        }    }        ReferenceList sparseProperties;    _prop.addSparseArrayPropertiesToReferenceList(sparseProperties, Object(this));    unsigned newLength = o + sparseProperties.length();    if (newLength > storageLength) {      resizeStorage(newLength);    }     ReferenceListIterator it = sparseProperties.begin();    while (it != sparseProperties.end()) {      Reference ref = it++;      storage[o] = ref.getValue(exec).imp();      ObjectImp::deleteProperty(exec, ref.getPropertyName(exec));      o++;    }        if (newLength != storageLength)        memset(storage + o, 0, sizeof(ValueImp *) * (storageLength - o));        return o;}// ------------------------------ ArrayPrototypeImp ----------------------------const ClassInfo ArrayPrototypeImp::info = {"Array", &ArrayInstanceImp::info, &arrayTable, 0};/* Source for array_object.lut.h@begin arrayTable 13  toString       ArrayProtoFuncImp::ToString       DontEnum|Function 0  toLocaleString ArrayProtoFuncImp::ToLocaleString DontEnum|Function 0  concat         ArrayProtoFuncImp::Concat         DontEnum|Function 1  join           ArrayProtoFuncImp::Join           DontEnum|Function 1  pop            ArrayProtoFuncImp::Pop            DontEnum|Function 0  push           ArrayProtoFuncImp::Push           DontEnum|Function 1  reverse        ArrayProtoFuncImp::Reverse        DontEnum|Function 0  shift          ArrayProtoFuncImp::Shift          DontEnum|Function 0  slice          ArrayProtoFuncImp::Slice          DontEnum|Function 2  sort           ArrayProtoFuncImp::Sort           DontEnum|Function 1  splice         ArrayProtoFuncImp::Splice         DontEnum|Function 2  unshift        ArrayProtoFuncImp::UnShift        DontEnum|Function 1@end*/// ECMA 15.4.4ArrayPrototypeImp::ArrayPrototypeImp(ExecState *exec,                                     ObjectPrototypeImp *objProto)  : ArrayInstanceImp(objProto, 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -