blob: a68d3174e74e61bca266ab2e0640043fc7a1f2e5 [file] [log] [blame]
Guido van Rossum12d12c51993-10-26 17:58:25 +00001/***********************************************************
2Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Range object implementation */
26
27#include "allobjects.h"
28
29typedef struct {
30 OB_HEAD
31 long start;
32 long step;
33 long len;
34 int reps;
35} rangeobject;
36
37
38object *
39newrangeobject(start, len, step, reps)
40 long start, len, step;
41 int reps;
42{
43 rangeobject *obj = (rangeobject *) newobject(&Rangetype);
44
45 obj->start = start;
46 obj->len = len;
47 obj->step = step;
48 obj->reps = reps;
49
50 return (object *) obj;
51}
52
53static void
54range_dealloc(r)
55 rangeobject *r;
56{
57 DEL(r);
58}
59
60static object *
61range_item(r, i)
62 rangeobject *r;
63 int i;
64{
65 if (i < 0 || i >= r->len * r->reps) {
66 err_setstr(IndexError, "range object index out of range");
67 return NULL;
68 }
69
70 return newintobject(r->start + (i % r->len) * r->step);
71}
72
73static int
74range_length(r)
75 rangeobject *r;
76{
77 return r->len * r->reps;
78}
79
80static object *
81range_repr(r)
82 rangeobject *r;
83{
84 char buf[80];
85 if (r->reps != 1)
86 sprintf(buf, "(xrange(%ld, %ld, %ld) * %d)",
87 r->start,
88 r->start + r->len * r->step,
89 r->step,
90 r->reps);
91 else
92 sprintf(buf, "xrange(%ld, %ld, %ld)",
93 r->start,
94 r->start + r->len * r->step,
95 r->step);
96 return newstringobject(buf);
97}
98
99object *
100range_concat(r, obj)
101 rangeobject *r;
102 object *obj;
103{
104 if (is_rangeobject(obj)) {
105 rangeobject *s = (rangeobject *)obj;
106 if (r->start == s->start && r->len == s->len &&
107 r->step == s->step)
108 return newrangeobject(r->start, r->len, r->step,
109 r->reps + s->reps);
110 }
111 err_setstr(TypeError, "cannot concatenate different range objects");
112 return NULL;
113}
114
115object *
116range_repeat(r, n)
117 rangeobject *r;
118 int n;
119{
120 if (n < 0)
121 return (object *) newrangeobject(0, 0, 1, 1);
122
123 else if (n == 1) {
124 INCREF(r);
125 return (object *) r;
126 }
127
128 else
129 return (object *) newrangeobject(
130 r->start,
131 r->len,
132 r->step,
133 r->reps * n);
134}
135
136static int
137range_compare(r1, r2)
138 rangeobject *r1, *r2;
139{
140 if (r1->start != r2->start)
141 return r1->start - r2->start;
142
143 else if (r1->step != r2->step)
144 return r1->step - r2->step;
145
146 else if (r1->len != r2->len)
147 return r1->len - r2->len;
148
149 else
150 return r1->reps - r2->reps;
151}
152
153static object *
154range_slice(r, low, high)
155 rangeobject *r;
156 int low, high;
157{
158 if (r->reps != 1) {
159 err_setstr(TypeError, "cannot slice a replicated range");
160 return NULL;
161 }
162 if (low < 0)
163 low = 0;
164 else if (low > r->len)
165 low = r->len;
166 if (high < 0)
167 high = 0;
168 if (high < low)
169 high = low;
170 else if (high > r->len)
171 high = r->len;
172
173 return (object *) newrangeobject(
174 low * r->step + r->start,
175 high - low,
176 r->step,
177 1);
178}
179
180static sequence_methods range_as_sequence = {
181 range_length, /*sq_length*/
182 range_concat, /*sq_concat*/
183 range_repeat, /*sq_repeat*/
184 range_item, /*sq_item*/
185 range_slice, /*sq_slice*/
186 0, /*sq_ass_item*/
187 0, /*sq_ass_slice*/
188};
189
190typeobject Rangetype = {
191 OB_HEAD_INIT(&Typetype)
192 0, /* Number of items for varobject */
193 "range", /* Name of this type */
194 sizeof(rangeobject), /* Basic object size */
195 0, /* Item size for varobject */
196 range_dealloc, /*tp_dealloc*/
197 0, /*tp_print*/
198 0, /*tp_getattr*/
199 0, /*tp_setattr*/
200 range_compare, /*tp_compare*/
201 range_repr, /*tp_repr*/
202 0, /*tp_as_number*/
203 &range_as_sequence, /*tp_as_sequence*/
204 0, /*tp_as_mapping*/
205};