tagged release 0.6.4
[parrot.git] / src / pmc / unmanagedstruct.pmc
blob9d21aa7fbf3c89b07dc211df94cd077b470293bd
1 /*
2 Copyright (C) 2001-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/unmanagedstruct.pmc - C struct with unmanaged memory
9 =head1 DESCRIPTION
11 PMC class to hold C C<struct>s that Parrot's not responsible for
12 disposing of.
14 Buffer can be accessed using keyed assignments to PMC. Out of
15 bounds access will very likely segfault.
17 =head2 Functions
19 =over 4
21 =cut
25 #include "parrot/parrot.h"
26 #include "parrot/compiler.h"
28 static INTVAL key_2_idx(PARROT_INTERP, PMC *pmc, PMC *key);
29 static size_t calc_offsets(PARROT_INTERP, PMC*, PMC *init, size_t toff);
33 =item C<static char *
34 char_offset_int(PARROT_INTERP, PMC *pmc, INTVAL ix, int *type)>
36 Returns the pointer for the element at index C<ix>, and sets the element
37 type in C<*type>.
39 =cut
43 static char *
44 char_offset_int(PARROT_INTERP, PMC *pmc, INTVAL ix, int *type)
46     size_t offs, n;
47     ix *= 3;
49     if (!PMC_pmc_val(pmc))
50         real_exception(interp, NULL, E_ValueError,
51                 "Missing struct initializer");
53     n = (size_t)VTABLE_elements(interp, PMC_pmc_val(pmc));
55     if ((size_t)ix >= n)
56         real_exception(interp, NULL, E_ValueError,
57                 "Non existent elements in struct "
58                 "ix = %d n=%d", (int)ix, (int)n);
60     /* use structure init */
61     *type = (int) VTABLE_get_integer_keyed_int(interp,
62         PMC_pmc_val(pmc), ix);
64     offs  = (size_t) VTABLE_get_integer_keyed_int(interp,
65         PMC_pmc_val(pmc), ix + 2);
67     return ((char *)PMC_data(pmc)) + offs;
72 =item C<static INTVAL
73 key_2_idx(PARROT_INTERP, PMC *pmc, PMC *key)>
75 Returns the index for the element associated with key C<*key>. Raises an
76 exception if the key doesn't exist.
78 =cut
82 static INTVAL
83 key_2_idx(PARROT_INTERP, PMC *pmc, PMC *key)
85     int ix = 0;
87     if (!PMC_pmc_val(pmc))
88         real_exception(interp, NULL, E_ValueError,
89                 "Missing struct initializer");
91     if (PObj_get_FLAGS(key) & KEY_string_FLAG) {
92         PMC * const types = PMC_pmc_val(pmc);
94         if (types->vtable->base_type == enum_class_OrderedHash) {
95             Hash       * const hash = (Hash *)PMC_struct_val(types);
96             HashBucket * const b    = parrot_hash_get_bucket(interp, hash,
97                 key_string(interp, key));
99             if (!b)
100                 real_exception(interp, NULL, E_KeyError, "key doesn't exist");
102             ix = b - hash->bs;
103         }
104         else
105             real_exception(interp, NULL, E_TypeError,
106                     "unhandled type aggregate");
108         ix /= 3;
109     }
110     else
111         ix = key_integer(interp, key);
113     return ix;
118 =item C<static char *
119 char_offset_key(PARROT_INTERP, PMC *pmc, PMC *key, int *type)>
121 Returns the pointer for the element associated with key C<*key>, and
122 sets the element type in C<*type>.
124 =cut
128 static char *
129 char_offset_key(PARROT_INTERP, PMC *pmc, PMC *key, int *type)
131     size_t offs, count, size, max;
132     int    ix;
133     PMC   *next, *init;
134     char  *p;
136 #ifdef STRUCT_DEBUG
137     trace_key_dump(interp, key);
138 #endif
140     ix   = key_2_idx(interp, pmc, key);
141     next = key_next(interp, key);
142     p    = char_offset_int(interp, pmc, ix, type);
143     ix  *= 3;
145     if (!next)
146         return p;
148     if (PObj_get_FLAGS(next) & KEY_integer_FLAG)
149         count = key_integer(interp, next);
150     else
151         count = 1;
153     init = PMC_pmc_val(pmc);
154     max  = (size_t)VTABLE_get_integer_keyed_int(interp, init, ix + 1);
156 #ifdef STRUCT_DEBUG
157     PIO_eprintf(interp, " count = %d ix = %d max = %d\n",
158             (int)count, (int)ix, (int)max);
159 #endif
161     if (*type == enum_type_struct_ptr || *type == enum_type_struct) {
162         /* the struct PMC is hanging off the initializer element
163          * as property "_struct"
164          */
165         PMC * const ptr = VTABLE_get_pmc_keyed_int(interp, init, ix);
166         init            = VTABLE_getprop(interp, ptr, CONST_STRING(interp, "_struct"));
168         PARROT_ASSERT(init &&
169             (init->vtable->base_type == enum_class_UnManagedStruct ||
170              init->vtable->base_type == enum_class_ManagedStruct));
172         /* array of structs */
173         if (max > 1) {
174             if (key_next(interp, next))
175                 next = key_next(interp, next);
177             offs = PMC_int_val(init);
179 #ifdef STRUCT_DEBUG
180             PIO_eprintf(interp, "offs = %d\n", (int)offs);
181 #endif
183             p += offs * count;
184         }
185         if (init->vtable->base_type == enum_class_UnManagedStruct) {
186             /* now point PMC_data of this struct to the real data */
187             if (*type == enum_type_struct_ptr) {
188                 /* that is either a pointer */
189                 PARROT_ASSERT((PTR2INTVAL(p) & (PARROT_PTR_ALIGNMENT - 1)) == 0);
190                 PMC_data(init) = *(void**)p;
191             }
192             else {
193                 /* or just an offset for nested structs */
194                 PMC_data(init) = p;
195             }
196         }
197         else if (init->vtable->base_type == enum_class_ManagedStruct &&
198             *type == enum_type_struct_ptr) {
199             /* a nested struct pointer belonging to us
200              * p is the location of the struct pointer in the
201              * outer struct, the inner is at PMC_data(init)
202              */
203             PARROT_ASSERT((PTR2INTVAL(p) & (PARROT_PTR_ALIGNMENT - 1)) == 0);
204             *(void **)p = PMC_data(init);
205         }
207         return char_offset_key(interp, init, next, type);
208     }
210     if (count >= max)
211         real_exception(interp, NULL, E_LookupError,
212                 "Non existent array element in struct: "
213                 "count = %d max=%d", (int)count, (int)max);
214     size = data_types[*type - enum_first_type].size;
215     return p + count * size;
220 =item C<static INTVAL
221 ret_int(PARROT_INTERP, const char *p, int type)>
223 Returns the element of type C<type> starting at C<*p> as an C<INTVAL>.
225 If, for example, C<char> or c<short> type size doesn't match, this will fail
226 we need some more configure support for type sizes.
228 =cut
232 static INTVAL
233 ret_int(PARROT_INTERP, const char *p, int type)
234     __attribute__nonnull__(1);
236 static INTVAL
237 ret_int(PARROT_INTERP, const char *p, int type)
239     switch (type) {
240         case enum_type_INTVAL:
241             return *(const INTVAL*) p;
243 #if INT_SIZE == 4
244         case enum_type_int32:
245         case enum_type_uint32:
246 #endif
248 #if INT_SIZE == 8
249         case enum_type_int64:
250         case enum_type_uint64:
251 #endif
253         case enum_type_int:
254             return *(const int *)p;
256 #if (LONG_SIZE == 4) && !(INT_SIZE == 4) /* Unlikely combination. */
257         case enum_type_int32:
258         case enum_type_uint32:
259 #endif
261 #if (LONG_SIZE == 8) && !(INT_SIZE == 8)
262         case enum_type_int64:
263         case enum_type_uint64:
264 #endif
266         case enum_type_long:
267         case enum_type_ulong:
268             return *(const long *)p;
270 #if SHORT_SIZE == 2
271         case enum_type_int16:
272         case enum_type_uint16:
273 #endif
275         /* If SHORT_SIZE != 2 getting int16s requires extra tricks. */
276         case enum_type_short:
277             return *(const short *)p;
278         case enum_type_uint8:
279         case enum_type_uchar:
280         {
281             const unsigned char *uc = (const unsigned char *)p;
282             return (INTVAL)*uc;
283         }
284         case enum_type_int8:
285         case enum_type_char:
286             return *p;
287         default:
288             real_exception(interp, NULL, 1,
289                 "returning unhandled int type in struct");
290     }
295 =item C<static FLOATVAL
296 ret_float(PARROT_INTERP, const char *p, int type)>
298 Returns the element of type C<type> starting at C<*p> as a C<FLOATVAL>.
300 =cut
304 static FLOATVAL
305 ret_float(PARROT_INTERP, const char *p, int type)
306     __attribute__nonnull__(1);
308 static FLOATVAL
309 ret_float(PARROT_INTERP, const char *p, int type)
311     switch (type) {
312         case enum_type_FLOATVAL:
313             return (FLOATVAL) *(const FLOATVAL *)p;
314         case enum_type_float:
315             return (FLOATVAL) *(const float *)p;
316         case enum_type_double:
317             return (FLOATVAL) *(const double *)p;
318         default:
319             real_exception(interp, NULL, 1,
320                 "returning unhandled float type in struct");
321     }
326 =item C<static STRING*
327 ret_string(PARROT_INTERP, char *p, int type)>
329 Returns the element of type C<type> starting at C<*p> as a Parrot string.
331 =cut
335 static STRING*
336 ret_string(PARROT_INTERP, char *p, int type)
338     if (type == enum_type_cstr) {
339         char  *cstr = *(char **) p;
340         size_t len  = strlen(cstr);
341         return string_make(interp, cstr, len, "iso-8859-1", PObj_external_FLAG);
342     }
344     real_exception(interp, NULL, E_TypeError,
345         "returning unhandled string type in struct");
350 =item C<static PMC*
351 ret_pmc(PARROT_INTERP, PMC *pmc, char *p, int type, INTVAL idx)>
353 Returns the element of type C<type> starting at C<*p> as a PMC.
355 =cut
359 static PMC*
360 ret_pmc(PARROT_INTERP, PMC *pmc, char *p, int type, INTVAL idx)
362     PMC *ret = NULL, *init, *ptr;
364     switch (type) {
365         case enum_type_func_ptr:
366             /* this is a raw function pointer - not a PMC */
367             ret  = *(PMC**) p;
369             /* now check if initializer has a signature attached */
370             init = PMC_pmc_val(pmc);
371             ptr  = VTABLE_get_pmc_keyed_int(interp, init, idx*3);
373             if (ptr->pmc_ext && PMC_metadata(ptr)) {
374                 STRING *signature_str = CONST_STRING(interp, "_signature");
375                 PMC *sig = VTABLE_getprop(interp, ptr, signature_str);
376                 if (VTABLE_defined(interp, sig)) {
377                     STRING *sig_str = VTABLE_get_string(interp, sig);
378                     ret             = pmc_new(interp, enum_class_NCI);
379                     VTABLE_set_pointer_keyed_str(interp, ret, sig_str,
380                             *(PMC **)p);
381                 }
382             }
384             return ret;
385         case enum_type_struct_ptr:
386             /* check the metadata for an initializer */
387             init = PMC_pmc_val(pmc);
388             ptr  = VTABLE_get_pmc_keyed_int(interp, init, idx * 3);
390             /* grab the struct from the metadata */
391             if (ptr->pmc_ext && PMC_metadata(ptr)) {
392                 ret = VTABLE_getprop(interp, ptr, CONST_STRING(interp, "_struct"));
393             }
394             else {
395                 real_exception(interp, NULL, E_TypeError,
396                         "no initializer available for nested struct");
397             }
399             /* assign the pointer */
400             PMC_data(ret) = *(void**)p;
402             return ret;
403         default:
404             real_exception(interp, NULL, E_TypeError,
405                     "returning unhandled pmc type (%d) in struct", type);
406     }
411 =item C<static void
412 set_int(PARROT_INTERP, char *p, int type, INTVAL value)>
414 =cut
418 static void
419 set_int(PARROT_INTERP, char *p, int type, INTVAL value)
421     switch (type) {
422         case enum_type_uint8:
423         case enum_type_int8:
424         case enum_type_char:
425         case enum_type_uchar:
426             *(char *)p = (char)(value & 0xff);
427             break;
428         case enum_type_INTVAL:
429             *(INTVAL *)p = value;
430             break;
431         case enum_type_int:
432             *(int *)p = value;
433             break;
434         case enum_type_int16:
435         case enum_type_uint16:
436         case enum_type_short:
437             *(short *)p = (short)value;
438             break;
439         default:
440             real_exception(interp, NULL, 1,
441                 "setting unhandled int type in struct");
442             break;
443     }
448 =item C<static void
449 set_float(PARROT_INTERP, char *p, int type, FLOATVAL value)>
451 Sets the value of the element of type C<type> starting at C<*p> to
452 C<value>.
454 =cut
458 static void
459 set_float(PARROT_INTERP, char *p, int type, FLOATVAL value)
461     switch (type) {
462         case enum_type_FLOATVAL:
463             *(FLOATVAL *)p = (FLOATVAL)value;
464             break;
465         case enum_type_float:
466             *(float *)p = (float)value;
467             break;
468         case enum_type_double:
469             *(double *)p = (double)value;
470             break;
471         default:
472             real_exception(interp, NULL, 1,
473                 "setting unhandled float type in struct");
474             break;
475     }
480 =item C<static void
481 set_string(PARROT_INTERP, char *p, int type, STRING *value)>
483 Sets the value of the element of type C<type> starting at C<*p> to
484 C<*value>.
486 =cut
490 static void
491 set_string(PARROT_INTERP, char *p, int type, STRING *value)
493     if (type == enum_type_cstr) {
494         /* assuming 0-terminated C-string here;
495          * we can't use string_to_cstring easily */
496         char *cstr  = value->strstart;
497         *(char **)p = cstr;
498     }
499     else
500         real_exception(interp, NULL, 1,
501             "setting unhandled string type in struct (%d)", type);
506 =item C<static int
507 calc_align(PARROT_INTERP, PMC *pmc, PMC *type_pmc,
508         int type, int offs)>
510 Alignment of contained structures is the alignment of the
511 biggest item in that C<struct>.
513 i386: C<long long> or C<double> is aligned on 4.
515 This is recursive as structure definitions.
517 =cut
521 static int
522 calc_align(PARROT_INTERP, PMC *pmc, PMC *type_pmc,
523         int type, int offs)
525     int  align       = data_types[type - enum_first_type].size;
526     PMC *nested      = NULL;
527     PMC *nested_init = NULL;
529     if (type == enum_type_struct || type == enum_type_struct_ptr) {
530         /* a nested structs alignment is the biggest item in it
531          * so go through that struct and check
532          */
533         nested = VTABLE_getprop(interp, type_pmc, CONST_STRING(interp, "_struct"));
534         nested_init = PMC_pmc_val(nested);
535     }
536     if (type == enum_type_struct) {
537         size_t i, n    = (size_t)VTABLE_elements(interp, nested_init);
538         int    a_max   = 0;
539         int    new_offs;
541         if (n % 3)
542             real_exception(interp, NULL, E_TypeError,
543                     "Illegal initializer for struct");
545         for (i = 0; i < n; i += 3) {
546             PMC *nested_type_pmc = VTABLE_get_pmc_keyed_int(interp,
547                     nested_init, i);
548             int  nested_type     = (int)VTABLE_get_integer(interp,
549                 nested_type_pmc);
550             new_offs             = calc_align(interp, nested,
551                     nested_type_pmc, nested_type, offs);
553             if (new_offs > a_max)
554                 a_max = new_offs;
555         }
557         align = a_max;
558     }
560     if (align && offs % align) {
561         const int diff = align - (offs % align);
562         offs += diff;
563     }
565     if (type == enum_type_struct || type == enum_type_struct_ptr)
566         calc_offsets(interp, nested, nested_init, 0);
568     return offs;
573 =item C<static size_t
574 calc_offsets(PARROT_INTERP, PMC *pmc, PMC *value, size_t toff)>
576 Calculates the offsets for the C<struct>. See C<init_pmc()> for a
577 description of C<*value>.
579 =cut
583 static size_t
584 calc_offsets(PARROT_INTERP, PMC *pmc, PMC *value, size_t toff)
586     size_t i, n = (size_t)VTABLE_elements(interp, value);
587     int size;
589     if (n % 3)
590         real_exception(interp, NULL, E_TypeError,
591                 "Illegal initializer for struct");
593     for (i = 0; i < n; i += 3) {
594         PMC *type_pmc = VTABLE_get_pmc_keyed_int(interp, value, i);
595         int  type     = (int)VTABLE_get_integer(interp, type_pmc);
596         int  count    = (int)VTABLE_get_integer_keyed_int(interp, value, i + 1);
597         int  offs     = (int)VTABLE_get_integer_keyed_int(interp, value, i + 2);
599         if (type < enum_first_type || type >= enum_last_type)
600             real_exception(interp, NULL, E_TypeError,
601                     "Illegal type in initializer for struct");
603         if (count <= 0) {
604             count = 1;
605             VTABLE_set_integer_keyed_int(interp, value, i+1, count);
606         }
608         if (offs <= 0) {
609             offs = toff = calc_align(interp, pmc, type_pmc, type, toff);
610             VTABLE_set_integer_keyed_int(interp, value, i+2, offs);
611         }
612         else
613             toff = offs;
615         if (type == enum_type_struct) {
616             PMC *nested = VTABLE_getprop(interp, type_pmc, CONST_STRING(interp, "_struct"));
617             size        = PMC_int_val(nested);
618         }
619         else
620             size = data_types[type - enum_first_type].size;
622         toff += count * size;
624         /* set / allocate size */
625         if (i == n - 3)
626             VTABLE_set_integer_native(interp, pmc, toff);
627     }
629     return toff;
632 pmclass UnManagedStruct extends default need_ext no_ro {
636 =back
638 =head2 Methods
640 =over 4
642 =item C<void init()>
644 Initializes the C<struct> with a default value of C<NULL>.
646 =cut
650     VTABLE void init() {
651         PMC_pmc_val(SELF) = NULL;
652     }
656 =item C<void init_pmc(PMC *value)>
658 Initialize the struct with some data.
660 C<*value> should be an array of triples of:
662 =over 4
664 =item 0
666 The datatype. See the C<enum> in F<include/parrot/datatypes.h>.
668 =item 1
670 The count.
672 =item 2
674 The offset.
676 =back
678 =cut
682     VTABLE void init_pmc(PMC *value) {
683         SELF.set_pmc(value);
684     }
688 =item C<void set_pmc(PMC *value)>
690 Sets C<*value> (see C<init_pmc()> and calculates the offsets.
692 =cut
696     VTABLE void set_pmc(PMC *value) {
697         PMC_pmc_val(SELF) = value;
698         PObj_custom_mark_SET(SELF);
699         calc_offsets(INTERP, SELF, value, 0);
700     }
704 =item C<void mark()>
706 Marks the C<struct> as live.
708 =cut
712     VTABLE void mark() {
713         if (PMC_pmc_val(SELF))
714             pobject_lives(INTERP, (PObj *)PMC_pmc_val(SELF));
715     }
719 =item C<INTVAL is_equal(PMC *value)>
721 Returns whether the two C<struct>s are equivalent.
723 =cut
727     VTABLE INTVAL is_equal(PMC *value) {
728         return (SELF->vtable == value->vtable &&
729             PMC_data(SELF) == PMC_data(value));
730     }
734 =item C<INTVAL defined()>
736 Returns whether the C<struct> is defined.
738 =cut
742     VTABLE INTVAL defined() {
743         return PMC_data(SELF) != NULL;
744     }
748 =item C<INTVAL get_integer()>
750 Returns the size of the C<struct>.
752 =cut
756     VTABLE INTVAL get_integer() {
757         return PMC_int_val(SELF);
758     }
762 =item C<void set_integer_native(INTVAL size)>
764 Sets the size of the C<struct>.
766 =cut
770     VTABLE void set_integer_native(INTVAL size) {
771         PMC_int_val(SELF) = size;
772     }
776 =item C<INTVAL get_integer_keyed_int(INTVAL ix)>
778 Returns the integer value at index C<ix>.
780 =cut
784     VTABLE INTVAL get_integer_keyed_int(INTVAL ix) {
785         int   type;
786         char *p = char_offset_int(INTERP, pmc, ix, &type);
787         return ret_int(INTERP, p, type);
788     }
792 =item C<INTVAL get_integer_keyed(PMC *key)>
794 Returns the integer value associated with C<*key>.
796 =cut
800     VTABLE INTVAL get_integer_keyed(PMC *key) {
801         int   type;
802         char *p = char_offset_key(INTERP, pmc, key, &type);
803         return ret_int(INTERP, p, type);
804     }
808 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
810 Returns the floating-point value at index C<ix>.
812 =cut
816     VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
817         int   type;
818         char *p = char_offset_int(INTERP, pmc, key, &type);
819         return ret_float(INTERP, p, type);
820     }
824 =item C<FLOATVAL get_number_keyed(PMC *key)>
826 Returns the floating-point value associated with C<*key>.
828 =cut
832     VTABLE FLOATVAL get_number_keyed(PMC *key) {
833         int   type;
834         char *p = char_offset_key(INTERP, pmc, key, &type);
835         return ret_float(INTERP, p, type);
836     }
840 =item C<STRING *get_string_keyed_int(INTVAL key)>
842 Returns the Parrot string value at index C<ix>.
844 =cut
848     VTABLE STRING *get_string_keyed_int(INTVAL key) {
849         int   type;
850         char *p = char_offset_int(INTERP, pmc, key, &type);
851         return ret_string(INTERP, p, type);
852     }
856 =item C<STRING *get_string_keyed(PMC *key)>
858 Returns the Parrot string value associated with C<*key>.
860 =cut
864     VTABLE STRING *get_string_keyed(PMC *key) {
865         int   type;
866         char *p = char_offset_key(INTERP, pmc, key, &type);
867         return ret_string(INTERP, p, type);
868     }
872 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
874 Returns the PMC value at index C<ix>.
876 =cut
880     VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
881         int   type;
882         char *p = char_offset_int(INTERP, pmc, key, &type);
883         return ret_pmc(INTERP, pmc, p, type, key);
884     }
888 =item C<PMC *get_pmc_keyed(PMC *key)>
890 Returns the PMC value associated with C<*key>.
892 =cut
896     VTABLE PMC *get_pmc_keyed(PMC *key) {
897         int   type;
898         char *p = char_offset_key(INTERP, pmc, key, &type);
899         return ret_pmc(INTERP, pmc, p, type, key_2_idx(INTERP, pmc, key));
900     }
904 =item C<void *get_pointer()>
906 Returns the pointer to the actual C C<struct>.
908 =cut
912     VTABLE void *get_pointer() {
913         return PMC_data(SELF);
914     }
918 =item C<void set_pointer(void *value)>
920 Set the pointer to the actual C C<struct>.
922 =cut
926     VTABLE void set_pointer(void *value) {
927         PMC_data(SELF) = value;
928     }
932 =item C<void set_integer_keyed_int(INTVAL ix, INTVAL value)>
934 Sets the value of the element at index C<ix> to C<value>.
936 =cut
940     VTABLE void set_integer_keyed_int(INTVAL ix, INTVAL value) {
941         int   type;
942         char *p = char_offset_int(INTERP, pmc, ix, &type);
943         set_int(INTERP, p, type, value);
944     }
948 =item C<void set_integer_keyed(PMC *key, INTVAL value)>
950 Sets the value of the element associated with key C<*key> to C<value>.
952 May cause segfaults if value is out of bounds.
954 =cut
958     VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
959         int   type;
960         char *p = char_offset_key(INTERP, pmc, key, &type);
961         set_int(INTERP, p, type, value);
962     }
966 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
968 Sets the value of the element at index C<ix> to C<value>.
970 =cut
974     VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
975         int   type;
976         char *p = char_offset_int(INTERP, pmc, key, &type);
977         set_float(INTERP, p, type, value);
978     }
982 =item C<void set_number_keyed(PMC *key, FLOATVAL value)>
984 Sets the value of the element associated with key C<*key> to C<value>.
986 =cut
990     VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
991         int type;
992         char *p = char_offset_key(INTERP, pmc, key, &type);
993         set_float(INTERP, p, type, value);
994     }
998 =item C<void set_string_keyed_int(INTVAL key, STRING *value)>
1000 Sets the value of the element at index C<key> to C<*value>.
1002 =cut
1006     VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
1007         int   type;
1008         char *p = char_offset_int(INTERP, pmc, key, &type);
1009         set_string(INTERP, p, type, value);
1010     }
1014 =item C<void set_string_keyed(PMC *key, STRING *value)>
1016 Sets the value of the element associated with key C<*key> to C<*value>.
1018 =cut
1022     VTABLE void set_string_keyed(PMC *key, STRING *value) {
1023         int   type;
1024         char *p = char_offset_key(INTERP, pmc, key, &type);
1025         set_string(INTERP, p, type, value);
1026     }
1032 =back
1034 =head1 HISTORY
1036 Initial revision by sean 2002/08/04
1038 =head1 SEE ALSO
1040 F<docs/pmc/struct.pod>
1042 =cut
1047  * Local variables:
1048  *   c-file-style: "parrot"
1049  * End:
1050  * vim: expandtab shiftwidth=4:
1051  */