001: // Copyright (c) Corporation for National Research Initiatives
002: package org.python.core;
003:
004: /**
005: Used to implement the builtin xrange function.
006:
007: Significant patches contributed by Jason Orendorff - jorendor@cbu.edu
008:
009: @author Jim Hugunin - hugunin@python.org
010: @since JPython 0.3
011: **/
012:
013: public class PyXRange extends PySequence {
014: public int start, stop, step; // directly from xrange(start, stop, step)
015: int cycleLength; // The length of an uncopied xrange
016: int copies; // The number of copies made (used to implement
017:
018: // xrange(x,y,z)*n)
019:
020: public PyXRange(int start, int stop, int step) {
021: if (step == 0)
022: throw Py.ValueError("zero step for xrange()");
023: this .start = start;
024: this .stop = stop;
025: this .step = step;
026: int oneLessThanStep = step + (step > 0 ? -1 : 1);
027: cycleLength = (stop - start + oneLessThanStep) / step;
028: if (cycleLength < 0) {
029: cycleLength = 0;
030: }
031: this .stop = start + cycleLength * step;
032: copies = 1;
033: }
034:
035: public int __len__() {
036: return cycleLength * copies;
037: }
038:
039: private int getInt(int i) {
040: if (cycleLength == 0) { // avoid divide by zero errors
041: return start;
042: } else {
043: return start + (i % cycleLength) * step;
044: }
045: }
046:
047: protected PyObject pyget(int i) {
048: return new PyInteger(getInt(i));
049: }
050:
051: protected PyObject getslice(int start, int stop, int step) {
052: Py.DeprecationWarning("xrange object slicing is deprecated; "
053: + "convert to list instead");
054: if (copies != 1) {
055: throw Py.TypeError("cannot slice a replicated range");
056: }
057: int len = sliceLength(start, stop, step);
058: int xslice_start = getInt(start);
059: int xslice_step = this .step * step;
060: int xslice_stop = xslice_start + xslice_step * len;
061: return new PyXRange(xslice_start, xslice_stop, xslice_step);
062: }
063:
064: protected PyObject repeat(int howmany) {
065: Py
066: .DeprecationWarning("xrange object multiplication is deprecated; "
067: + "convert to list instead");
068: PyXRange x = new PyXRange(start, stop, step);
069: x.copies = copies * howmany;
070: return x;
071: }
072:
073: public PyObject __add__(PyObject generic_other) {
074: throw Py.TypeError("cannot concatenate xrange objects");
075: }
076:
077: public PyObject __findattr__(String name) {
078: String msg = "xrange object's 'start', 'stop' and 'step' "
079: + "attributes are deprecated";
080: if (name == "start") {
081: Py.DeprecationWarning(msg);
082: return Py.newInteger(start);
083: } else if (name == "stop") {
084: Py.DeprecationWarning(msg);
085: return Py.newInteger(stop);
086: } else if (name == "step") {
087: Py.DeprecationWarning(msg);
088: return Py.newInteger(step);
089: } else {
090: return super .__findattr__(name);
091: }
092: }
093:
094: public int hashCode() {
095: // Not the greatest hash function
096: // but then again hashing xrange's is rather uncommon
097: return stop ^ start ^ step;
098: }
099:
100: public String toString() {
101: StringBuffer buf = new StringBuffer("xrange(");
102: if (start != 0) {
103: buf.append(start);
104: buf.append(", ");
105: }
106: buf.append(__len__() * step + start);
107: if (step != 1) {
108: buf.append(", ");
109: buf.append(step);
110: }
111: buf.append(")");
112: return buf.toString();
113: }
114:
115: public PyList tolist() {
116: Py.DeprecationWarning("xrange.tolist() is deprecated; "
117: + "use list(xrange) instead");
118: PyList list = new PyList();
119: int count = __len__();
120: for (int i = 0; i < count; i++) {
121: list.append(pyget(i));
122: }
123: return list;
124: }
125: }
|