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

📄 nativearray.java

📁 RESIN 3.2 最新源码
💻 JAVA
字号:
/* * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the *   Free SoftwareFoundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.es;/** * JavaScript object */class NativeArray extends Native {  static ESId LENGTH = ESId.intern("length");  static final int NEW = 1;  static final int JOIN = NEW + 1;  static final int TO_STRING = JOIN + 1;  static final int REVERSE = TO_STRING + 1;  static final int SORT = REVERSE + 1;  // js1.2  static final int CONCAT = SORT + 1;  static final int POP = CONCAT + 1;  static final int PUSH = POP + 1;  static final int SHIFT = PUSH + 1;  static final int UNSHIFT = SHIFT + 1;  static final int SLICE = UNSHIFT + 1;  static final int SPLICE = SLICE + 1;  /**   * Create a new object based on a prototype   */  private NativeArray(String name, int n, int len)  {    super(name, len);    this.n = n;  }  /**   * Creates the native Array object   */  static ESObject create(Global resin)  {    Native nativeArray = new NativeArray("Array", NEW, 1);    ESArray proto = new ESArray();    proto.prototype = resin.objProto;    NativeWrapper array = new NativeWrapper(resin, nativeArray,                                            proto, ESThunk.ARRAY_THUNK);    resin.arrayProto = proto;    put(proto, "join", JOIN, 1);    put(proto, "toString", TO_STRING, 0);    put(proto, "reverse", REVERSE, 0);    put(proto, "sort", SORT, 0);    // js1.2    put(proto, "concat", CONCAT, 0);    put(proto, "pop", POP, 0);    put(proto, "push", PUSH, 0);    put(proto, "shift", SHIFT, 0);    put(proto, "unshift", UNSHIFT, 0);    put(proto, "slice", SLICE, 2);    put(proto, "splice", SPLICE, 0);    proto.setClean();    array.setClean();    return array;  }  private static void put(ESObject obj, String name, int n, int len)  {    ESId id = ESId.intern(name);    obj.put(id, new NativeArray(name, n, len), DONT_ENUM);  }  public ESBase call(Call eval, int length) throws Throwable  {    switch (n) {    case NEW:      return create(eval, length);    case JOIN:      if (length == 0)        return toString(eval, length);      else        return join(eval, length);    case TO_STRING:      return toString(eval, length);    case REVERSE:      return reverse(eval, length);    case SORT:      return sort(eval, length);    case CONCAT:      return concat(eval, length);    case POP:      return pop(eval, length);    case PUSH:      return push(eval, length);    case SHIFT:      return shift(eval, length);    case UNSHIFT:      return unshift(eval, length);    case SLICE:      return slice(eval, length);    case SPLICE:      return splice(eval, length);    default:      throw new ESException("Unknown object function");    }  }  ESBase create(Call eval, int length) throws Throwable  {    ESObject obj = Global.getGlobalProto().createArray();    if (length == 0)      return obj;    if (length == 1) {      ESBase arg = eval.getArg(0);      if (arg instanceof ESNumber)        obj.setProperty(LENGTH, ESNumber.create(arg.toInt32()));      else        obj.setProperty(0, arg);      return obj;    }    for (int i = 0; i < length; i++)      obj.setProperty(i, eval.getArg(i));    return obj;  }  static ESBase join(ESObject array, String separator) throws Throwable  {    if (array.mark != 0) {      return ESString.create("...");    }    array.mark = -1;    try {      int len = array.getProperty(LENGTH).toInt32();      StringBuffer sbuf = new StringBuffer();      for (int i = 0; i < len; i++) {        if (i != 0)          sbuf.append(separator);        ESBase value = array.hasProperty(i);        if (value != null && value != esNull && value != esUndefined)          sbuf.append(value.toString());      }      return ESString.create(sbuf.toString());    } finally {      array.mark = 0;    }  }  ESBase join(Call eval, int length) throws Throwable  {    String separator = length == 0 ? "," : eval.getArg(0).toString();    ESObject array = eval.getArg(-1).toObject();    return join(array, separator);  }  static ESBase toString(ESObject array) throws Throwable  {    return join(array, ",");  }  // XXX: different for non-js1.2  ESBase toString(Call eval, int length) throws Throwable  {    ESObject array = eval.getArg(-1).toObject();    return toString(array);  }  ESBase reverse(Call eval, int length) throws Throwable  {    ESObject array = eval.getArg(-1).toObject();    int len = (int) array.getProperty(LENGTH).toInt32();    for (int k = 0; k < len / 2; k++) {      int firstIndex = k;      int secondIndex = len - k - 1;      ESBase first = array.hasProperty(firstIndex);      ESBase second = array.hasProperty(secondIndex);      if (first == null)        array.delete(secondIndex);      else        array.setProperty(secondIndex, first);      if (second == null)        array.delete(firstIndex);      else        array.setProperty(firstIndex, second);    }    return array;  }  ESBase sort(Call eval, int length) throws Throwable  {    ESObject array = eval.getArg(-1).toObject();    ESBase cmp = length == 0 ? null : eval.getArg(0);    int len = (int) array.getProperty(LENGTH).toInt32();    ESBase []values = new ESBase[len];    for (int i = 0; i < len; i++)      values[i] = array.getProperty("" + i);    qsort(values, 0, len, cmp);    for (int i = 0; i < len; i++) {      if (values[i] == esUndefined)        array.delete("" + i);      else        array.setProperty("" + i, values[i]);    }    return array;  }  private void qsort(ESBase []array, int offset, int length, ESBase cmp)    throws Throwable  {    if (length == 2) {      if (compare(cmp, array[offset], array[offset + 1]) > 0) {        ESBase temp = array[offset];        array[offset] = array[offset + 1];        array[offset + 1] = temp;      }    } else if (length > 2) {      int keyIndex = offset + length / 2;      ESBase key = array[keyIndex];      int keys = 0;      int tail = 0;      int val;      if ((val = compare(cmp, array[offset], key)) > 0) {        key = array[offset];        array[offset] = array[keyIndex];        array[keyIndex] = key;      } else if (val == 0)        keys++;      if ((val = compare(cmp, key, array[offset + length - 1])) > 0) {        key = array[offset + length - 1];        array[offset + length - 1] = array[keyIndex];        array[keyIndex] = key;        keys = 0;        tail = 1;        if ((val = compare(cmp, array[offset], key)) > 0) {          key = array[offset];          array[offset] = array[keyIndex];          array[keyIndex] = key;        } else if (val == 0)          keys++;      } else if (val < 0)        tail = 1;      int i;      if (keyIndex == offset + 1) {        i = 2 + tail;        keys++;      }      else        i = 1 + tail;      for (; i < length; i++) {        int index = offset + i - tail;        if (array[index] == key) {          keys++;          continue;        }        int cmpResult = compare(cmp, key, array[index]);        if (cmpResult > 0 && keys != 0) {          ESBase temp = array[index];          array[index] = array[index - keys];          array[index - keys] = temp;        } else if (cmpResult < 0) {          ESBase temp = array[offset + length - tail - 1];          array[offset + length - tail - 1] = array[index];          array[index] = temp;          tail += 1;        } else if (cmpResult == 0)          keys++;      }      if (length - tail - keys > 1)        qsort(array, offset, length - tail - keys, cmp);      if (tail > 1)        qsort(array, offset + length - tail, tail, cmp);    }  }  private int compare(ESBase cmp, ESBase a, ESBase b)    throws Throwable  {    if (a == b)      return 0;    else if (a == esUndefined)      return 1;    else if (b == esUndefined)      return -1;    else if (a == esNull)      return 1;    else if (b == esNull)      return -1;    else if (cmp != null) {      // Call eval = new Call(ESGlobal.getGlobalProto(), false);      Global resin = Global.getGlobalProto();      Call eval = resin.getCall();      eval.stack[0] = esNull;      eval.stack[1] = a;      eval.stack[2] = b;      eval.top = 1;      int result = cmp.call(eval, 2).toInt32();      resin.freeCall(eval);      return result;    }    else {      String sa = a.toString();      String sb = b.toString();      return sa.compareTo(sb);    }  }  ESBase concat(Call eval, int length) throws Throwable  {    ESArray array = Global.getGlobalProto().createArray();    int k = 0;    for (int i = -1; i < length; i++) {      ESBase arg = eval.getArg(i);      if (arg == esNull || arg == esUndefined || arg == esEmpty)        continue;      ESBase arglen = arg.hasProperty(LENGTH);      if (arglen == null) {        array.setProperty(k++, arg);        continue;      }      int len = (int) arglen.toInt32();      if (len < 0) {        array.setProperty(k++, arg);        continue;      }      for (int j = 0; j < len; j++) {        ESBase obj = arg.hasProperty(j);        if (obj != null)          array.setProperty(k, obj);        k++;      }    }    array.setProperty(LENGTH, ESNumber.create(k));    return array;  }  ESBase pop(Call eval, int length) throws Throwable  {    ESObject obj = eval.getArg(-1).toObject();    ESBase lenObj = obj.hasProperty(LENGTH);    int len;    if (lenObj == null || (len = lenObj.toInt32()) <= 0)      return esUndefined;    ESBase value = obj.getProperty(len - 1);    obj.setProperty(LENGTH, ESNumber.create(len - 1));    return value;  }  ESBase push(Call eval, int length) throws Throwable  {    ESObject obj = eval.getArg(-1).toObject();    ESBase lenObj = obj.getProperty(LENGTH);    int len = lenObj.toInt32();    if (len < 0)      len = 0;    for (int i = 0; i < length; i++)      obj.setProperty(len + i, eval.getArg(i));    ESNumber newLen = ESNumber.create(len + length);    obj.setProperty(LENGTH, newLen);    return newLen;  }  ESBase shift(Call eval, int length) throws Throwable  {    ESObject obj = eval.getArg(-1).toObject();    ESBase lenObj = obj.hasProperty(LENGTH);    int len;    if (lenObj == null || (len = (int) lenObj.toInt32()) <= 0)      return esUndefined;    ESBase value = obj.getProperty(0);    for (int i = 1; i < len; i++) {      ESBase temp = obj.hasProperty(i);      if (temp == null)        obj.delete(ESString.create(i - 1));      else        obj.setProperty(i - 1, temp);    }    obj.setProperty(LENGTH, ESNumber.create(len - 1));    return value;  }  ESBase unshift(Call eval, int length) throws Throwable  {    ESObject obj = eval.getArg(-1).toObject();    ESBase lenObj = obj.getProperty(LENGTH);    int len = lenObj.toInt32();    if (len < 0)      len = 0;    if (length == 0)      return ESNumber.create(0);    for (int i = len - 1; i >= 0; i--) {      ESBase value = obj.getProperty(i);      if (value == null)        obj.delete(ESString.create(length + i));      else        obj.setProperty(length + i, value);    }    for (int i = 0; i < length; i++) {      ESBase value = eval.getArg(i);      if (value == null)        obj.delete(ESString.create(i));      else        obj.setProperty(i, value);    }    ESNumber numLen = ESNumber.create(len + length);    obj.setProperty(LENGTH, numLen);    return numLen;  }  ESBase slice(Call eval, int length) throws Throwable  {    ESObject obj = eval.getArg(-1).toObject();    ESBase lenObj = obj.getProperty(LENGTH);    int len = lenObj.toInt32();    ESArray array = Global.getGlobalProto().createArray();    if (len <= 0)      return array;    int start = 0;    if (length > 0)      start = eval.getArg(0).toInt32();    if (start < 0)      start += len;    if (start < 0)      start = 0;    if (start > len)      return array;    int end = len;    if (length > 1)      end = eval.getArg(1).toInt32();    if (end < 0)      end += len;    if (end < 0)      return array;    if (end > len)      end = len;    if (start >= end)      return array;    for (int i = 0; i < end - start; i++) {      ESBase value = obj.hasProperty(start + i);      if (value != null)        array.setProperty(i, value);    }    array.setProperty(LENGTH, ESNumber.create(end - start));    return array;  }  ESBase splice(Call eval, int length) throws Throwable  {    if (length < 2)      return esUndefined;    ESObject obj = eval.getArg(-1).toObject();    int index = eval.getArg(0).toInt32();    int count = eval.getArg(1).toInt32();    boolean single = count == 1;    ESBase lenObj = obj.getProperty(LENGTH);    int len = lenObj.toInt32();    if (index < 0)      index += len;    if (index < 0)      index = 0;    if (count < 0)      count = 0;    if (index + count > len)      count = len - index;    ESBase value;    if (count < 1)      value = esUndefined;    else {      value = Global.getGlobalProto().createArray();      for (int i = 0; i < count; i++)        value.setProperty(i, obj.getProperty(index + i));    }    int delta = length - 2 - count;    if (delta < 0) {      for (int i = 0; i < len - count; i++) {        ESBase temp = obj.getProperty(i + index + count);        if (temp == null)          obj.delete(ESString.create(i + index + count + delta));        else          obj.setProperty(i + index + count + delta, temp);      }    } else if (delta > 0) {      for (int i = len - count - 1; i >= 0; i--) {        ESBase temp = obj.getProperty(i + index + count);        if (temp == null)          obj.delete(ESString.create(i + index + count + delta));        else          obj.setProperty(i + index + count + delta, temp);      }    }    for (int i = 0; i < length - 2; i++)      obj.setProperty(i + index, eval.getArg(i + 2));    obj.setProperty(LENGTH, ESNumber.create(len - count + length - 2));    return value;  }}

⌨️ 快捷键说明

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