blob: 1275ebab72c4d9a07d702ac9c5e76b300e552b5c [file] [log] [blame]
Guido van Rossum81daa321993-05-20 14:24:46 +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/* Access object implementation */
26
27#include "allobjects.h"
28
29#include "structmember.h"
30#include "modsupport.h" /* For getargs() etc. */
31
32typedef struct {
33 OB_HEAD
34 object *ac_value;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000035 object *ac_owner;
Guido van Rossum81daa321993-05-20 14:24:46 +000036 typeobject *ac_type;
37 int ac_mode;
38} accessobject;
39
40/* Forward */
41static int typecheck PROTO((object *, typeobject *));
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000042static int ownercheck PROTO((object *, object *, int, int));
Guido van Rossum81daa321993-05-20 14:24:46 +000043
44object *
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000045newaccessobject(value, owner, type, mode)
Guido van Rossum81daa321993-05-20 14:24:46 +000046 object *value;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000047 object *owner;
Guido van Rossum81daa321993-05-20 14:24:46 +000048 typeobject *type;
49 int mode;
50{
51 accessobject *ap;
Guido van Rossum81daa321993-05-20 14:24:46 +000052 if (!typecheck(value, type)) {
53 err_setstr(AccessError,
54 "access: initial value has inappropriate type");
55 return NULL;
56 }
57 ap = NEWOBJ(accessobject, &Accesstype);
58 if (ap == NULL)
59 return NULL;
60 XINCREF(value);
61 ap->ac_value = value;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000062 XINCREF(owner);
63 ap->ac_owner = owner;
Guido van Rossum81daa321993-05-20 14:24:46 +000064 XINCREF(type);
65 ap->ac_type = (typeobject *)type;
66 ap->ac_mode = mode;
67 return (object *)ap;
68}
69
70object *
71cloneaccessobject(op)
72 object *op;
73{
74 register accessobject *ap;
75 if (!is_accessobject(op)) {
76 err_badcall();
77 return NULL;
78 }
79 ap = (accessobject *)op;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000080 return newaccessobject(ap->ac_value, ap->ac_owner,
Guido van Rossum81daa321993-05-20 14:24:46 +000081 ap->ac_type, ap->ac_mode);
82}
83
84void
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000085setaccessowner(op, owner)
Guido van Rossum81daa321993-05-20 14:24:46 +000086 object *op;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000087 object *owner;
Guido van Rossum81daa321993-05-20 14:24:46 +000088{
89 register accessobject *ap;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000090 if (!is_accessobject(op))
Guido van Rossum81daa321993-05-20 14:24:46 +000091 return; /* XXX no error */
92 ap = (accessobject *)op;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000093 XDECREF(ap->ac_owner);
94 XINCREF(owner);
95 ap->ac_owner = owner;
Guido van Rossum81daa321993-05-20 14:24:46 +000096}
97
Guido van Rossumb3f72581993-05-21 19:56:10 +000098int
99hasaccessvalue(op)
100 object *op;
101{
102 if (!is_accessobject(op))
103 return 0;
104 return ((accessobject *)op)->ac_value != NULL;
105}
106
Guido van Rossum81daa321993-05-20 14:24:46 +0000107object *
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000108getaccessvalue(op, owner)
Guido van Rossum81daa321993-05-20 14:24:46 +0000109 object *op;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000110 object *owner;
Guido van Rossum81daa321993-05-20 14:24:46 +0000111{
112 register accessobject *ap;
113 if (!is_accessobject(op)) {
114 err_badcall();
115 return NULL;
116 }
117 ap = (accessobject *)op;
118
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000119 if (!ownercheck(owner, ap->ac_owner, AC_R, ap->ac_mode)) {
Guido van Rossum81daa321993-05-20 14:24:46 +0000120 err_setstr(AccessError, "read access denied");
121 return NULL;
122 }
123
124 if (ap->ac_value == NULL) {
125 err_setstr(AccessError, "no current value");
126 return NULL;
127 }
128 INCREF(ap->ac_value);
129 return ap->ac_value;
130}
131
132int
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000133setaccessvalue(op, owner, value)
Guido van Rossum81daa321993-05-20 14:24:46 +0000134 object *op;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000135 object *owner;
Guido van Rossum81daa321993-05-20 14:24:46 +0000136 object *value;
137{
138 register accessobject *ap;
139 if (!is_accessobject(op)) {
140 err_badcall();
141 return -1;
142 }
143 ap = (accessobject *)op;
144
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000145 if (!ownercheck(owner, ap->ac_owner, AC_W, ap->ac_mode)) {
Guido van Rossum81daa321993-05-20 14:24:46 +0000146 err_setstr(AccessError, "write access denied");
147 return -1;
148 }
149
150 if (!typecheck(value, ap->ac_type)) {
151 err_setstr(AccessError, "assign value of inappropriate type");
152 return -1;
153 }
154
155 if (value == NULL) { /* Delete it */
156 if (ap->ac_value == NULL) {
157 err_setstr(AccessError, "no current value");
158 return -1;
159 }
160 DECREF(ap->ac_value);
161 ap->ac_value = NULL;
162 return 0;
163 }
164 XDECREF(ap->ac_value);
165 INCREF(value);
166 ap->ac_value = value;
167 return 0;
168}
169
170static int
171typecheck(value, type)
172 object *value;
173 typeobject *type;
174{
175 object *x;
176 if (value == NULL || type == NULL)
177 return 1; /* No check */
178 if (value->ob_type == type)
179 return 1; /* Exact match */
180 if (type == &Anynumbertype) {
181 if (value->ob_type->tp_as_number == NULL)
182 return 0;
183 if (!is_instanceobject(value))
184 return 1;
185 /* For instances, make sure it really looks like a number */
186 x = getattr(value, "__sub__");
187 if (x == NULL) {
188 err_clear();
189 return 0;
190 }
191 DECREF(x);
192 return 1;
193 }
194 if (type == &Anysequencetype) {
195 if (value->ob_type->tp_as_sequence == NULL)
196 return 0;
197 if (!is_instanceobject(value))
198 return 1;
199 /* For instances, make sure it really looks like a sequence */
200 x = getattr(value, "__getslice__");
201 if (x == NULL) {
202 err_clear();
203 return 0;
204 }
205 DECREF(x);
206 return 1;
207 }
208 if (type == &Anymappingtype) {
209 if (value->ob_type->tp_as_mapping == NULL)
210 return 0;
211 if (!is_instanceobject(value))
212 return 1;
213 /* For instances, make sure it really looks like a mapping */
214 x = getattr(value, "__getitem__");
215 if (x == NULL) {
216 err_clear();
217 return 0;
218 }
219 DECREF(x);
220 return 1;
221 }
222 return 0;
223}
224
225static int
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000226ownercheck(caller, owner, access, mode)
Guido van Rossum81daa321993-05-20 14:24:46 +0000227 object *caller;
228 object *owner;
229 int access;
230 int mode;
231{
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000232 int mask = AC_PUBLIC;
233 if (owner != NULL) {
234 if (caller == owner)
235 mask |= AC_PRIVATE | AC_PROTECTED;
236 else if (is_classobject(owner) && issubclass(caller, owner))
237 mask |= AC_PROTECTED;
238 }
239 return access & mode & mask;
Guido van Rossum81daa321993-05-20 14:24:46 +0000240}
241
242/* Access methods */
243
244static void
245access_dealloc(ap)
246 accessobject *ap;
247{
248 XDECREF(ap->ac_value);
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000249 XDECREF(ap->ac_owner);
Guido van Rossum81daa321993-05-20 14:24:46 +0000250 XDECREF(ap->ac_type);
251 DEL(ap);
252}
253
254#define OFF(x) offsetof(accessobject, x)
255
256static struct memberlist access_memberlist[] = {
257 {"ac_value", T_OBJECT, OFF(ac_value)},
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000258 {"ac_owner", T_OBJECT, OFF(ac_owner)},
Guido van Rossum81daa321993-05-20 14:24:46 +0000259 {"ac_type", T_OBJECT, OFF(ac_type)},
260 {"ac_mode", T_INT, OFF(ac_mode)},
261 {NULL} /* Sentinel */
262};
263
264static object *
265access_getattr(ap, name)
266 accessobject *ap;
267 char *name;
268{
269 return getmember((char *)ap, access_memberlist, name);
270}
271
272static object *
273access_repr(ap)
274 accessobject *ap;
275{
276 char buf[300];
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000277 char buf2[20];
278 char *ownername;
Guido van Rossum81daa321993-05-20 14:24:46 +0000279 typeobject *type = ap->ac_type;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000280 if (is_classobject(ap->ac_owner)) {
281 ownername =
282 getstringvalue(((classobject *)ap->ac_owner)->cl_name);
283 }
284 else {
285 sprintf(buf2, "0x%lx", (long)ap->ac_owner);
286 ownername = buf2;
287 }
Guido van Rossumb3f72581993-05-21 19:56:10 +0000288 sprintf(buf,
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000289 "<access object, value 0x%lx, owner %.100s, type %.100s, mode %04o>",
Guido van Rossumb3f72581993-05-21 19:56:10 +0000290 (long)(ap->ac_value),
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000291 ownername,
Guido van Rossum81daa321993-05-20 14:24:46 +0000292 type ? type->tp_name : "-",
293 ap->ac_mode);
294 return newstringobject(buf);
295}
296
297typeobject Accesstype = {
298 OB_HEAD_INIT(&Typetype)
299 0, /*ob_size*/
300 "access", /*tp_name*/
301 sizeof(accessobject), /*tp_size*/
302 0, /*tp_itemsize*/
303 /* methods */
304 access_dealloc, /*tp_dealloc*/
305 0, /*tp_print*/
306 access_getattr, /*tp_getattr*/
307 0, /*tp_setattr*/
308 0, /*tp_compare*/
309 access_repr, /*tp_repr*/
310 0, /*tp_as_number*/
311 0, /*tp_as_sequence*/
312 0, /*tp_as_mapping*/
313 0, /*tp_hash*/
314};
315
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000316
317/* Pseudo type objects to indicate collections of types */
Guido van Rossum81daa321993-05-20 14:24:46 +0000318
319/* XXX This should be replaced by a more general "subclassing"
320 XXX mechanism for type objects... */
321
322typeobject Anynumbertype = {
323 OB_HEAD_INIT(&Typetype)
324 0, /*ob_size*/
325 "*number*", /*tp_name*/
326};
327
328/* XXX Should really distinguish mutable and immutable sequences as well */
329
330typeobject Anysequencetype = {
331 OB_HEAD_INIT(&Typetype)
332 0, /*ob_size*/
333 "*sequence*", /*tp_name*/
334};
335
336typeobject Anymappingtype = {
337 OB_HEAD_INIT(&Typetype)
338 0, /*ob_size*/
339 "*mapping*", /*tp_name*/
340};