blob: f19dad89ec33f41eaaeda3636ab7301777a1c2c6 [file] [log] [blame]
Guido van Rossum12d12c51993-10-26 17:58:25 +00001/***********************************************************
Guido van Rossum7d6aa511993-12-21 22:50:31 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
Guido van Rossum12d12c51993-10-26 17:58:25 +00004
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;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000034 int reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000035} rangeobject;
36
37
38object *
Guido van Rossum7d6aa511993-12-21 22:50:31 +000039newrangeobject(start, len, step, reps)
Guido van Rossum12d12c51993-10-26 17:58:25 +000040 long start, len, step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000041 int reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000042{
43 rangeobject *obj = (rangeobject *) newobject(&Rangetype);
44
45 obj->start = start;
46 obj->len = len;
47 obj->step = step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000048 obj->reps = reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000049
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{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000065 if (i < 0 || i >= r->len * r->reps) {
Guido van Rossum12d12c51993-10-26 17:58:25 +000066 err_setstr(IndexError, "range object index out of range");
67 return NULL;
68 }
69
Guido van Rossum7d6aa511993-12-21 22:50:31 +000070 return newintobject(r->start + (i % r->len) * r->step);
Guido van Rossum12d12c51993-10-26 17:58:25 +000071}
72
73static int
74range_length(r)
75 rangeobject *r;
76{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000077 return r->len * r->reps;
78}
79
80static int
81range_print(r, fp, flags)
82 rangeobject *r;
83 FILE *fp;
84 int flags;
85{
86 int i, j;
87
88 fprintf(fp, "(");
89 for (i = 0; i < r->reps; ++i)
90 for (j = 0; j < r->len; ++j) {
91 if (j > 0 || i > 0)
92 fprintf(fp, ", ");
93
94 fprintf(fp, "%d", r->start + j * r->step);
95 }
96
97 if (r->len == 1 && r->reps == 1)
98 fprintf(fp, ",");
99 fprintf(fp, ")");
100 return 0;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000101}
102
103static object *
104range_repr(r)
105 rangeobject *r;
106{
107 char buf[80];
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000108 sprintf(buf, "(range(%ld, %ld, %ld) * %d)",
109 r->start,
110 r->start + r->len * r->step,
111 r->step,
112 r->reps);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000113 return newstringobject(buf);
114}
115
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000116object *
117range_concat(r, obj)
118 rangeobject *r;
119 object *obj;
120{
121 err_setstr(TypeError, "cannot concatenate range objects");
122 return NULL;
123}
124
125object *
126range_repeat(r, n)
127 rangeobject *r;
128 int n;
129{
130 if (n < 0)
131 return (object *) newrangeobject(0, 0, 1, 1);
132
133 else if (n == 1) {
134 INCREF(r);
135 return (object *) r;
136 }
137
138 else
139 return (object *) newrangeobject(
140 r->start,
141 r->len,
142 r->step,
143 r->reps * n);
144}
145
Guido van Rossum12d12c51993-10-26 17:58:25 +0000146static int
147range_compare(r1, r2)
148 rangeobject *r1, *r2;
149{
150 if (r1->start != r2->start)
151 return r1->start - r2->start;
152
153 else if (r1->step != r2->step)
154 return r1->step - r2->step;
155
156 else if (r1->len != r2->len)
157 return r1->len - r2->len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000158
159 else
160 return r1->reps - r2->reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000161}
162
163static object *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000164range_slice(r, low, high)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000165 rangeobject *r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000166 int low, high;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000167{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000168 if (r->reps != 1) {
169 err_setstr(TypeError, "cannot slice a replicated range");
170 return NULL;
171 }
172 if (low < 0)
173 low = 0;
174 else if (low > r->len)
175 low = r->len;
176 if (high < 0)
177 high = 0;
178 if (high < low)
179 high = low;
180 else if (high > r->len)
181 high = r->len;
182
183 if (low == 0 && high == r->len) {
184 INCREF(r);
185 return (object *) r;
186 }
187
188 return (object *) newrangeobject(
189 low * r->step + r->start,
190 high - low,
191 r->step,
192 1);
Guido van Rossum2586bf01993-11-01 16:21:44 +0000193}
Guido van Rossum12d12c51993-10-26 17:58:25 +0000194
Guido van Rossum2586bf01993-11-01 16:21:44 +0000195static object *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000196range_tolist(self, args)
197rangeobject *self;
198object *args;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000199{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000200 object *thelist;
201 int j;
202 int len = self->len * self->reps;
203
204 if (! getargs(args, ""))
205 return NULL;
206
207 if ((thelist = newlistobject(len)) == NULL)
208 return NULL;
209
210 for (j = 0; j < len; ++j)
211 if ((setlistitem(thelist, j,
212 (object *) newintobject(
213 self->start + (j % self->len) * self->step))) < 0)
214 return NULL;
215
216 return thelist;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000217}
218
219static object *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000220range_getattr(r, name)
Guido van Rossum2586bf01993-11-01 16:21:44 +0000221 rangeobject *r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000222 char *name;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000223{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000224 static struct methodlist range_methods[] = {
225 {"tolist", range_tolist},
226 {NULL, NULL}
227 };
228
229 return findmethod(range_methods, (object *) r, name);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000230}
231
232static sequence_methods range_as_sequence = {
233 range_length, /*sq_length*/
234 range_concat, /*sq_concat*/
235 range_repeat, /*sq_repeat*/
236 range_item, /*sq_item*/
237 range_slice, /*sq_slice*/
238 0, /*sq_ass_item*/
239 0, /*sq_ass_slice*/
240};
241
242typeobject Rangetype = {
243 OB_HEAD_INIT(&Typetype)
244 0, /* Number of items for varobject */
Guido van Rossum2586bf01993-11-01 16:21:44 +0000245 "xrange", /* Name of this type */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000246 sizeof(rangeobject), /* Basic object size */
247 0, /* Item size for varobject */
248 range_dealloc, /*tp_dealloc*/
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000249 range_print, /*tp_print*/
250 range_getattr, /*tp_getattr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000251 0, /*tp_setattr*/
252 range_compare, /*tp_compare*/
253 range_repr, /*tp_repr*/
254 0, /*tp_as_number*/
255 &range_as_sequence, /*tp_as_sequence*/
256 0, /*tp_as_mapping*/
257};