blob: caadc77ca921398c210026cd38ea58096a433144 [file] [log] [blame]
Guido van Rossum12d12c51993-10-26 17:58:25 +00001/***********************************************************
Guido van Rossum6610ad91995-01-04 19:07:38 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum12d12c51993-10-26 17:58:25 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum12d12c51993-10-26 17:58:25 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum12d12c51993-10-26 17:58:25 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum12d12c51993-10-26 17:58:25 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum12d12c51993-10-26 17:58:25 +000029
30******************************************************************/
31
32/* Range object implementation */
33
34#include "allobjects.h"
35
36typedef struct {
37 OB_HEAD
38 long start;
39 long step;
40 long len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000041 int reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000042} rangeobject;
43
44
45object *
Guido van Rossum7d6aa511993-12-21 22:50:31 +000046newrangeobject(start, len, step, reps)
Guido van Rossum12d12c51993-10-26 17:58:25 +000047 long start, len, step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000048 int reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000049{
Guido van Rossum6c02a2f1996-07-22 16:16:25 +000050 rangeobject *obj = NEWOBJ(rangeobject, &Rangetype);
Guido van Rossum12d12c51993-10-26 17:58:25 +000051
52 obj->start = start;
53 obj->len = len;
54 obj->step = step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000055 obj->reps = reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000056
57 return (object *) obj;
58}
59
60static void
61range_dealloc(r)
62 rangeobject *r;
63{
64 DEL(r);
65}
66
67static object *
68range_item(r, i)
69 rangeobject *r;
70 int i;
71{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000072 if (i < 0 || i >= r->len * r->reps) {
Guido van Rossum12d12c51993-10-26 17:58:25 +000073 err_setstr(IndexError, "range object index out of range");
74 return NULL;
75 }
76
Guido van Rossum7d6aa511993-12-21 22:50:31 +000077 return newintobject(r->start + (i % r->len) * r->step);
Guido van Rossum12d12c51993-10-26 17:58:25 +000078}
79
80static int
81range_length(r)
82 rangeobject *r;
83{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000084 return r->len * r->reps;
85}
86
87static int
88range_print(r, fp, flags)
89 rangeobject *r;
90 FILE *fp;
91 int flags;
92{
93 int i, j;
94
95 fprintf(fp, "(");
96 for (i = 0; i < r->reps; ++i)
97 for (j = 0; j < r->len; ++j) {
98 if (j > 0 || i > 0)
99 fprintf(fp, ", ");
100
101 fprintf(fp, "%d", r->start + j * r->step);
102 }
103
104 if (r->len == 1 && r->reps == 1)
105 fprintf(fp, ",");
106 fprintf(fp, ")");
107 return 0;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000108}
109
110static object *
111range_repr(r)
112 rangeobject *r;
113{
114 char buf[80];
Guido van Rossum03093a21994-09-28 15:51:32 +0000115 sprintf(buf, "(xrange(%ld, %ld, %ld) * %d)",
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000116 r->start,
117 r->start + r->len * r->step,
118 r->step,
119 r->reps);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000120 return newstringobject(buf);
121}
122
Guido van Rossumce005091995-01-17 16:33:39 +0000123static object *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000124range_concat(r, obj)
125 rangeobject *r;
126 object *obj;
127{
128 err_setstr(TypeError, "cannot concatenate range objects");
129 return NULL;
130}
131
Guido van Rossumce005091995-01-17 16:33:39 +0000132static object *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000133range_repeat(r, n)
134 rangeobject *r;
135 int n;
136{
137 if (n < 0)
138 return (object *) newrangeobject(0, 0, 1, 1);
139
140 else if (n == 1) {
141 INCREF(r);
142 return (object *) r;
143 }
144
145 else
146 return (object *) newrangeobject(
147 r->start,
148 r->len,
149 r->step,
150 r->reps * n);
151}
152
Guido van Rossum12d12c51993-10-26 17:58:25 +0000153static int
154range_compare(r1, r2)
155 rangeobject *r1, *r2;
156{
157 if (r1->start != r2->start)
158 return r1->start - r2->start;
159
160 else if (r1->step != r2->step)
161 return r1->step - r2->step;
162
163 else if (r1->len != r2->len)
164 return r1->len - r2->len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000165
166 else
167 return r1->reps - r2->reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000168}
169
170static object *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000171range_slice(r, low, high)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000172 rangeobject *r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000173 int low, high;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000174{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000175 if (r->reps != 1) {
176 err_setstr(TypeError, "cannot slice a replicated range");
177 return NULL;
178 }
179 if (low < 0)
180 low = 0;
181 else if (low > r->len)
182 low = r->len;
183 if (high < 0)
184 high = 0;
185 if (high < low)
186 high = low;
187 else if (high > r->len)
188 high = r->len;
189
190 if (low == 0 && high == r->len) {
191 INCREF(r);
192 return (object *) r;
193 }
194
195 return (object *) newrangeobject(
196 low * r->step + r->start,
197 high - low,
198 r->step,
199 1);
Guido van Rossum2586bf01993-11-01 16:21:44 +0000200}
Guido van Rossum12d12c51993-10-26 17:58:25 +0000201
Guido van Rossum2586bf01993-11-01 16:21:44 +0000202static object *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000203range_tolist(self, args)
204rangeobject *self;
205object *args;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000206{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000207 object *thelist;
208 int j;
209 int len = self->len * self->reps;
210
211 if (! getargs(args, ""))
212 return NULL;
213
214 if ((thelist = newlistobject(len)) == NULL)
215 return NULL;
216
217 for (j = 0; j < len; ++j)
218 if ((setlistitem(thelist, j,
219 (object *) newintobject(
220 self->start + (j % self->len) * self->step))) < 0)
221 return NULL;
222
223 return thelist;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000224}
225
226static object *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000227range_getattr(r, name)
Guido van Rossum2586bf01993-11-01 16:21:44 +0000228 rangeobject *r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000229 char *name;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000230{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000231 static struct methodlist range_methods[] = {
Guido van Rossum03093a21994-09-28 15:51:32 +0000232 {"tolist", (method)range_tolist},
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000233 {NULL, NULL}
234 };
235
236 return findmethod(range_methods, (object *) r, name);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000237}
238
239static sequence_methods range_as_sequence = {
Guido van Rossum03093a21994-09-28 15:51:32 +0000240 (inquiry)range_length, /*sq_length*/
241 (binaryfunc)range_concat, /*sq_concat*/
242 (intargfunc)range_repeat, /*sq_repeat*/
243 (intargfunc)range_item, /*sq_item*/
244 (intintargfunc)range_slice, /*sq_slice*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000245 0, /*sq_ass_item*/
246 0, /*sq_ass_slice*/
247};
248
249typeobject Rangetype = {
250 OB_HEAD_INIT(&Typetype)
251 0, /* Number of items for varobject */
Guido van Rossum2586bf01993-11-01 16:21:44 +0000252 "xrange", /* Name of this type */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000253 sizeof(rangeobject), /* Basic object size */
254 0, /* Item size for varobject */
Guido van Rossum03093a21994-09-28 15:51:32 +0000255 (destructor)range_dealloc, /*tp_dealloc*/
256 (printfunc)range_print, /*tp_print*/
257 (getattrfunc)range_getattr, /*tp_getattr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000258 0, /*tp_setattr*/
Guido van Rossum03093a21994-09-28 15:51:32 +0000259 (cmpfunc)range_compare, /*tp_compare*/
260 (reprfunc)range_repr, /*tp_repr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000261 0, /*tp_as_number*/
262 &range_as_sequence, /*tp_as_sequence*/
263 0, /*tp_as_mapping*/
264};