001: /*
002: * $Id: AnyRange.java,v 1.24 2002/09/16 08:05:02 jkl Exp $
003: *
004: * Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
005: *
006: * Use is subject to license terms, as defined in
007: * Anvil Sofware License, Version 1.1. See LICENSE
008: * file, or http://njet.org/license-1.1.txt
009: */
010: package anvil.core;
011:
012: import anvil.script.Context;
013: import anvil.java.util.BindingEnumeration;
014: import java.io.IOException;
015: import java.io.OutputStream;
016: import java.io.Writer;
017:
018: /// @class range
019: /// Range represents range of values from <i>start</i> to <i>end</i>,
020: /// where <i>start</i> is inclusive and <i>end</i> is exclusive.
021:
022: /**
023: * class AnyRange
024: *
025: * @author: Jani Lehtimäki
026: */
027: public class AnyRange extends Any {
028:
029: /// @constructor range
030: /// Creates range.
031: /// @synopsis range(int start, int end)
032: /// @synopsis range(int start, int end, int step)
033: /// @param start Starting index (inclusive)
034: /// @param end Ending index (inclusive)
035: /// @param step Step
036: public static final Object[] newInstance = { "start", "end",
037: "*step", null };
038:
039: public static final Any newInstance(Any a, Any b, Any c) {
040: if (c == null) {
041: return new AnyRange(a, b);
042: } else {
043: return new AnyRange(a, b, c);
044: }
045: }
046:
047: transient public static final anvil.script.compiler.NativeClass __class__ = new anvil.script.compiler.NativeClass(
048: "range",
049: AnyRange.class,
050: //DOC{{
051: ""
052: + " @class range\n"
053: + " Range represents range of values from <i>start</i> to <i>end</i>,\n"
054: + " where <i>start</i> is inclusive and <i>end</i> is exclusive.\n"
055: + " @constructor range \n"
056: + " Creates range.\n"
057: + " @synopsis range(int start, int end)\n"
058: + " @synopsis range(int start, int end, int step)\n"
059: + " @param start Starting index (inclusive)\n"
060: + " @param end Ending index (inclusive)\n"
061: + " @param step Step\n"
062: //}}DOC
063: );
064:
065: protected Any _left;
066: protected Any _right;
067: protected Any _step = Any.NULL;
068: protected boolean _ascend;
069:
070: private AnyRange() {
071: }
072:
073: public AnyRange(Any left, Any right) {
074: _left = left.isUndefined() ? NEG_INF : left;
075: _right = right.isUndefined() ? INF : right;
076: _ascend = _left.compareTo(_right) <= 0;
077: }
078:
079: public AnyRange(Any left, Any right, Any step) {
080: _left = left.isUndefined() ? NEG_INF : left;
081: _right = right.isUndefined() ? INF : right;
082: _step = step;
083: _ascend = _left.compareTo(_right) <= 0;
084: }
085:
086: public final anvil.script.ClassType classOf() {
087: return __class__;
088: }
089:
090: public int typeOf() {
091: return IS_RANGE;
092: }
093:
094: public int sizeOf() {
095: int size = _right.toInt() - _left.toInt();
096: if (size < 0) {
097: size = -size;
098: }
099: return size;
100: }
101:
102: public boolean isRange() {
103: return true;
104: }
105:
106: public boolean toBoolean() {
107: return true;
108: }
109:
110: public Any getLeft() {
111: return _left;
112: }
113:
114: public Any getRight() {
115: return _right;
116: }
117:
118: public Any getMin() {
119: return _ascend ? _left : _right;
120: }
121:
122: public Any getMax() {
123: return _ascend ? _right : _left;
124: }
125:
126: public Any[] toTuple() {
127: return new Any[] { _left, _right };
128: }
129:
130: public Object toObject() {
131: return new Any[] { _left, _right };
132: }
133:
134: public AnyRange toRange() {
135: return this ;
136: }
137:
138: public int hashCode() {
139: return _left.hashCode() + _right.hashCode();
140: }
141:
142: public String toString() {
143: return _left.toString() + ".." + _right.toString();
144: }
145:
146: public Writer toAnvil(Writer writer) throws IOException {
147: _left.toAnvil(writer);
148: writer.write('.');
149: writer.write('.');
150: _right.toAnvil(writer);
151: return writer;
152: }
153:
154: public Writer toJava(Writer writer) throws IOException {
155: writer.write("new anvil.core.AnyRange(");
156: _left.toJava(writer);
157: writer.write(',');
158: writer.write(' ');
159: _right.toJava(writer);
160: writer.write(')');
161: return writer;
162: }
163:
164: public anvil.codec.Code toCode(anvil.codec.Code code) {
165: anvil.codec.ConstantPool pool = code.getPool();
166: int clazz = pool.addClass("anvil/core/AnyRange");
167: code.anew(clazz);
168: code.dup();
169: _left.toCode(code);
170: _right.toCode(code);
171: code.invokespecial(pool.addMethodRef(clazz, "<init>",
172: "(Lanvil/core/Any;Lanvil/core/Any;)V"));
173: return code;
174: }
175:
176: public Object clone() {
177: return this ;
178: }
179:
180: public Any copy() {
181: return new AnyRange(_left.copy(), _right.copy());
182: }
183:
184: public boolean equals(Object obj) {
185: if (this == obj) {
186: return true;
187: }
188: if (obj instanceof AnyRange) {
189: AnyRange r = (AnyRange) obj;
190: return _left.equals(r._left) && _right.equals(r._right);
191: }
192: return false;
193: }
194:
195: protected int compare(Any other) {
196: AnyRange range = other.toRange();
197: int delta = _left.compareTo(range._left);
198: if (delta == 0) {
199: delta = _right.compareTo(range._right);
200: }
201: return delta;
202: }
203:
204: public void serialize(Serializer serializer) throws IOException {
205: if (serializer.register(this )) {
206: return;
207: }
208: serializer.write('r');
209: _left.serialize(serializer);
210: _right.serialize(serializer);
211: }
212:
213: public static final AnyRange unserialize(Unserializer unserializer)
214: throws UnserializationException {
215: AnyRange range = new AnyRange();
216: unserializer.register(range);
217: range._left = unserializer.unserialize();
218: range._right = unserializer.unserialize();
219: range._ascend = range._left.compareTo(range._right) <= 0;
220: return range;
221: }
222:
223: public Any getReference(Context context, Any index) {
224: int i = index.toInt();
225: if (i == 0) {
226: return _left;
227: } else if (i == 1) {
228: return _right;
229: } else {
230: throw context.ReferenceError("range[" + index + "]");
231: }
232: }
233:
234: public Any checkReference(Context context, Any index) {
235: int i = index.toInt();
236: if (i == 0) {
237: return _left;
238: } else if (i == 1) {
239: return _right;
240: } else {
241: return UNDEFINED;
242: }
243: }
244:
245: public boolean inRange(Any value, boolean withright) {
246: int cmp = (withright ? 1 : 0);
247: if (_ascend) {
248: return (_left.compareTo(value) <= 0)
249: && (value.compareTo(_right) < cmp);
250: } else {
251: return (_right.compareTo(value) < cmp)
252: && (value.compareTo(_left) <= 0);
253: }
254: }
255:
256: public boolean contains(Any value) {
257: if (value.isRange()) {
258: AnyRange r = value.toRange();
259: return inRange(r.getLeft(), true)
260: && inRange(r.getRight(), true);
261: } else {
262: return inRange(value, false);
263: }
264: }
265:
266: public Any getAttribute(Context context, String attribute) {
267: if (attribute.equals("left")) {
268: return _left;
269: } else if (attribute.equals("right")) {
270: return _right;
271: } else if (attribute.equals("step")) {
272: return _step;
273: } else {
274: throw context.AttributeError("range." + attribute);
275: }
276: }
277:
278: public BindingEnumeration enumeration() {
279: int left = _left.toInt();
280: int right = _right.toInt();
281: return new RangeEnumeration(left, right, _step.toInt());
282: }
283:
284: public class RangeEnumeration implements BindingEnumeration {
285:
286: private int _lo;
287: private int _hi;
288: private int _step;
289: private int _pos;
290: private int _index = 0;
291: private boolean _ascend;
292:
293: public RangeEnumeration(int lo, int hi, int step) {
294: if (step == 0) {
295: step = 1;
296: } else if (step < 0) {
297: step = -step;
298: }
299: _lo = lo;
300: _hi = hi;
301: _pos = _lo;
302: _ascend = (lo < hi);
303: _step = step;
304: }
305:
306: public boolean hasMoreElements() {
307: if (_ascend) {
308: return (_pos < _hi);
309: } else {
310: return (_pos > _hi);
311: }
312: }
313:
314: public Object nextElement() {
315: _index++;
316: if (_ascend) {
317: if (_pos >= _hi) {
318: return UNDEFINED;
319: }
320: Any next = Any.create(_pos);
321: _pos += _step;
322: return next;
323:
324: } else {
325: if (_pos < _hi) {
326: return UNDEFINED;
327: }
328: Any next = Any.create(_pos);
329: _pos -= _step;
330: return next;
331: }
332: }
333:
334: public Object nextKey() {
335: return Any.create(_index);
336: }
337: }
338:
339: }
|