[t] Refactor some namespace pmc tests to use throws_like
[parrot.git] / src / pmc / cpointer.pmc
blob8fe3435135d0ee3124cfd0201416df6afdd73652
1 /*
2 Copyright (C) 2008-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/cpointer.pmc - CPointer
9 =head1 DESCRIPTION
11 The CPointer PMC creates a PMC abstraction for a typed C pointer. It is
12 particularly used by the C<CallSignature> PMC, for the return values of a
13 C-level PCC invocation using a C<CallSignature> to pass the arguments and fetch
14 the results.
16 =head2 Attributes
18 A CPointer PMC has two attributes:
20 =over 4
22 =item pointer
24 A C<void *> pointer to an integer, number, string, or PMC.
26 =item sig
28 A string signature for the pointer. The possible signature values follow the
29 standard defined for PCC.
31   I   a Parrot integer (INTVAL)
32   N   a Parrot number  (FLOATVAL)
33   S   a Parrot string  (STRING *)
34   P   a Parrot object  (PMC *)
36 =back
39 =head2 Vtable Functions
41 These are the vtable functions for the CPointer class.
43 =over 4
45 =cut
49 pmclass CPointer auto_attrs {
50     ATTR void   *pointer; /* The stored pointer. */
51     ATTR STRING *sig;     /* A string signature for the pointer. */
55 =item C<void init()>
57 Initializes the pointer object.
59 =cut
63     VTABLE void init() {
64         SET_ATTR_pointer(INTERP, SELF, NULL);
65         SET_ATTR_sig(INTERP, SELF, NULL);
67         PObj_custom_mark_destroy_SETALL(SELF);
68     }
72 =item C<void mark()>
74 Marks the signature as live. Also marks a STRING or PMC pointed to by the
75 pointer.
77 =cut
81     VTABLE void mark() {
82         STRING *sig;
83         GET_ATTR_sig(INTERP, SELF, sig);
84         if (sig) {
85             void *pointer;
86             GET_ATTR_pointer(INTERP, SELF, pointer);
87             Parrot_gc_mark_PObj_alive(interp, (PObj *)sig);
89             if (pointer) {
90                 if (Parrot_str_equal(interp, sig, CONST_STRING(interp, "P"))) {
91                     PMC ** const pmc_pointer = (PMC **) pointer;
92                     PARROT_ASSERT(*pmc_pointer);
93                     Parrot_gc_mark_PObj_alive(interp, (PObj *) *pmc_pointer);
94                 }
95                 else if (Parrot_str_equal(interp, sig, CONST_STRING(interp, "S"))) {
96                     STRING ** const str_pointer = (STRING **) pointer;
97                     PARROT_ASSERT(*str_pointer);
98                     Parrot_gc_mark_PObj_alive(interp, (PObj *) *str_pointer);
99                 }
100             }
101         }
102     }
106 =item C<void destroy()>
108 Destroys the PMC and frees all allocated memory.
110 =cut
114     VTABLE void destroy() {
115     }
119 =item C<PMC *clone()>
121 Creates and returns a clone of the pointer.
123 =cut
127     VTABLE PMC *clone() {
128         PMC * const dest = pmc_new_noinit(INTERP, SELF->vtable->base_type);
129         PObj_custom_mark_SET(dest);
130         PMC_data(dest) = PMC_data(SELF);
131         return dest;
132     }
136 =item C<void *get_pointer()>
138 Returns the pointer.
140 =cut
144     VTABLE void *get_pointer() {
145         Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
146         return data->pointer;
147     }
151 =item C<void set_pointer(void *)>
153 Sets the pointer.
155 =cut
159     VTABLE void set_pointer(void *value) {
160         Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
161         data->pointer = value;
162     }
166 =item C<STRING *get_string_keyed_str(STRING *key)>
168 Returns the string signature.
170 =cut
174     VTABLE STRING *get_string_keyed_str(STRING *key) {
175         Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
176         UNUSED(key)
178         return data->sig;
179     }
183 =item C<void set_string_keyed_str(STRING *key, STRING *value)>
185 Sets the string signature.
187 =cut
191     VTABLE void set_string_keyed_str(STRING *key, STRING *value) {
192         Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
193         UNUSED(key)
195         data->sig = value;
196     }
200 =item C<INTVAL get_integer()>
202 Returns the integer value that the pointer points to (if the pointer is to an
203 integer or PMC).
205 =cut
209     VTABLE INTVAL get_integer() {
210         Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
212         if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "I"))) {
213             const INTVAL * const int_pointer = (INTVAL *) data->pointer;
214             return *int_pointer;
215         }
216         else if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "P"))) {
217             PMC ** const pmc_pointer = (PMC **) data->pointer;
218             return VTABLE_get_integer(interp, *pmc_pointer);
219         }
220         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
221                 "Unable to fetch integer value, the pointer is not an integer");
223     }
227 =item C<void set_integer_native(INTVAL value)>
229 Sets the integer value that the pointer points to (if the pointer is to an
230 integer or PMC).
232 =cut
236     VTABLE void set_integer_native(INTVAL value) {
237         Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
239         if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "I"))) {
240             INTVAL * const int_pointer = (INTVAL *) data->pointer;
241             *int_pointer = value;
242         }
243         else if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "P"))) {
244             PMC ** const pmc_pointer = (PMC **) data->pointer;
245             VTABLE_set_integer_native(interp, *pmc_pointer, value);
246         }
247         else {
248             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
249                     "Unable to set integer value, the pointer is not an integer");
250         }
251     }
255 =item C<FLOATVAL get_number()>
257 Returns the floating point value that the pointer points to (if the pointer is
258 to a number or PMC).
260 =cut
264     VTABLE FLOATVAL get_number() {
265         Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
267         if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "N"))) {
268             const FLOATVAL * const num_pointer = (FLOATVAL *) data->pointer;
269             return *num_pointer;
270         }
271         else if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "P"))) {
272             PMC ** const pmc_pointer = (PMC **) data->pointer;
273             return VTABLE_get_number(interp, *pmc_pointer);
274         }
275         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
276                 "Unable to fetch number value, the pointer is not a number");
277     }
281 =item C<void set_number_native(FLOATVAL value)>
283 Sets the floating point value that the pointer points to (if the pointer is
284 to a number or PMC).
286 =cut
290     VTABLE void set_number_native(FLOATVAL value) {
291         Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
293         if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "N"))) {
294             FLOATVAL * const num_pointer = (FLOATVAL *) data->pointer;
295             *num_pointer = value;
296         }
297         else if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "P"))) {
298             PMC ** const pmc_pointer = (PMC **) data->pointer;
299             VTABLE_set_number_native(interp, *pmc_pointer, value);
300         }
301         else {
302             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
303                     "Unable to set number value, the pointer is not a number");
304         }
305     }
309 =item C<STRING *get_string()>
311 Returns the Parrot string value that the pointer points to (if the pointer is
312 to a string or PMC).
314 =cut
318     VTABLE STRING *get_string() {
319         Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
321         if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "S"))) {
322             STRING ** const str_pointer = (STRING **) data->pointer;
323             return *str_pointer;
324         }
325         else if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "P"))) {
326             PMC ** const pmc_pointer = (PMC **) data->pointer;
327             return VTABLE_get_string(interp, *pmc_pointer);
328         }
329         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
330                 "Unable to fetch string value, the pointer is not a string");
331     }
335 =item C<void set_string_native(STRING *value)>
337 Sets the Parrot string value that the pointer points to (if the pointer is
338 to a string or PMC).
340 =cut
344     VTABLE void set_string_native(STRING *value) {
345         Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
347         if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "S"))) {
348             STRING ** const str_pointer = (STRING **) data->pointer;
349             *str_pointer = value;
350         }
351         else if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "P"))) {
352             PMC ** const pmc_pointer = (PMC **) data->pointer;
353             VTABLE_set_string_native(interp, *pmc_pointer, value);
354         }
355         else {
356             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
357                     "Unable to set string value, the pointer is not a string");
358         }
359     }
363 =item C<PMC *get_pmc()>
365 Returns the PMC value that the pointer points to (if the pointer is to a PMC).
367 =cut
371     VTABLE PMC *get_pmc() {
372         const Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
374         if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "P"))) {
375             PMC ** const pmc_pointer = (PMC **) data->pointer;
376             return *pmc_pointer;
377         }
378         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
379                 "Unable to fetch PMC value, the pointer is not a PMC");
380     }
384 =item C<void set_pmc(PMC *value)>
386 Sets the PMC value that the pointer points to (if the pointer is to a PMC).
388 =cut
392     VTABLE void set_pmc(PMC *value) {
393         const Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
395         if (Parrot_str_equal(interp, data->sig, CONST_STRING(interp, "P"))) {
396             PMC ** const pmc_pointer = (PMC **) data->pointer;
397             *pmc_pointer = value;
398         }
399         else {
400             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
401                     "Unable to set PMC value, the pointer is not a PMC");
402         }
403     }
407 =item C<INTVAL get_bool()>
409 Returns whether the pointer is not C<NULL>.
411 =cut
415     VTABLE INTVAL get_bool() {
416         const Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
417         return (INTVAL)(data->pointer != NULL);
418     }
422 =item C<INTVAL is_same(PMC *pmc2)>
424 Returns whether the pointer has the same value as C<*pmc2>.
426 =cut
430     VTABLE INTVAL is_same(PMC *pmc2) {
431         const Parrot_CPointer_attributes * const data = PARROT_CPOINTER(SELF);
432         return (INTVAL)(SELF->vtable  == pmc2->vtable &&
433                         data->pointer == VTABLE_get_pointer(interp, pmc2));
434     }
439 =back
441 =cut
446  * Local variables:
447  *   c-file-style: "parrot"
448  * End:
449  * vim: expandtab shiftwidth=4:
450  */