001: /*
002: * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.es;
030:
031: import com.caucho.util.CharBuffer;
032: import com.caucho.util.IntMap;
033:
034: import java.util.ArrayList;
035: import java.util.Iterator;
036:
037: /**
038: * JavaScript object
039: */
040: class ESArray extends ESObject {
041: static ESId LENGTH = ESId.intern("length");
042:
043: /**
044: * Create a new object based on a prototype
045: */
046: ESArray() {
047: super ("Array", null);
048: put(LENGTH, ESNumber.create(0), DONT_ENUM | DONT_DELETE);
049: }
050:
051: public void setProperty(int i, ESBase value) throws Throwable {
052: super .setProperty(ESString.create(i), value);
053:
054: int length = getProperty(LENGTH).toInt32();
055: if (i >= length)
056: super .setProperty(LENGTH, ESNumber.create(i + 1));
057: }
058:
059: public void setProperty(ESString key, ESBase value)
060: throws Throwable {
061: if (key.equals(LENGTH)) {
062: int oldLength;
063: int newLength;
064:
065: try {
066: oldLength = getProperty(LENGTH).toInt32();
067: newLength = value.toInt32();
068: } catch (ESException e) {
069: return;
070: }
071:
072: for (int i = newLength; i < oldLength; i++) {
073: try {
074: delete(ESString.create(i));
075: } catch (Exception e) {
076: }
077: }
078:
079: if (newLength < 0)
080: newLength = 0;
081:
082: super .setProperty(LENGTH, ESNumber.create(newLength));
083: return;
084: }
085:
086: super .setProperty(key, value);
087:
088: try {
089: int keyValue = Integer.parseInt(key.toString());
090: int length = getProperty(LENGTH).toInt32();
091:
092: if (keyValue >= length)
093: super
094: .setProperty(LENGTH, ESNumber
095: .create(keyValue + 1));
096: } catch (Exception e) {
097: }
098: }
099:
100: static ESString arrayToSource(ESObject obj, IntMap map,
101: boolean isLoopPass) throws Throwable {
102: Global resin = Global.getGlobalProto();
103: CharBuffer cb = new CharBuffer();
104:
105: int mark = map.get(obj);
106:
107: if (mark > 0 && isLoopPass)
108: return null;
109: else if (mark > 0) {
110: cb.append("#" + mark + "=");
111: map.put(obj, -mark);
112: } else if (mark == 0 && isLoopPass) {
113: map.put(obj, resin.addMark());
114: return null;
115: } else if (mark < 0 && !isLoopPass) {
116: return ESString.create("#" + -mark + "#");
117: }
118:
119: if (isLoopPass)
120: map.put(obj, 0);
121:
122: int len = obj.getProperty(LENGTH).toInt32();
123:
124: boolean noValue = true;
125: cb.append("[");
126: for (int i = 0; i < len; i++) {
127: if (i != 0)
128: cb.append(", ");
129:
130: ESBase value = obj.hasProperty(i);
131:
132: if (value != null && value != esNull
133: && value != esUndefined && value != esEmpty) {
134: if (isLoopPass)
135: value.toSource(map, isLoopPass);
136: else
137: cb.append(value.toSource(map, isLoopPass));
138: } else if (i + 1 == len)
139: cb.append(",");
140: }
141: cb.append("]");
142:
143: return ESString.create(cb.toString());
144: }
145:
146: public Iterator keys() throws ESException {
147: ArrayList values = new ArrayList();
148:
149: try {
150: int len = getProperty(LENGTH).toInt32();
151: for (int i = 0; i < len; i++) {
152: Object prop = getProperty(i);
153: // spec says add the key integers
154: values.add(String.valueOf(i));
155: }
156: } catch (Throwable e) {
157: throw ESWrapperException.create(e);
158: }
159:
160: return values.iterator();
161: }
162:
163: public ESString toSource(IntMap map, boolean isLoopPass)
164: throws Throwable {
165: return arrayToSource(this , map, isLoopPass);
166: }
167:
168: public ESObject dup() {
169: return new ESArray(false);
170: }
171:
172: protected ESArray(boolean dummy) {
173: }
174: }
|