Sun-Solaris-Exacct
view release on metacpan or search on metacpan
Object/Object.xs view on Meta::CPAN
/*
* Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Object.xs contains XS code for exacct file manipulation.
*/
#pragma ident "@(#)Object.xs 1.2 03/03/13 SMI"
#include <strings.h>
#include "../exacct_common.xh"
/* Pull in the file generated by extract_defines. */
#include "ObjectDefs.xi"
/* From Catalog.xs. */
extern char *catalog_id_str(ea_catalog_t catalog);
/*
* Copy an xs_ea_object_t. If the perl_obj part is null, we just copy the
* ea_object_t part. If the perl_obj part is not null and the Object is an
* Item it must be because the Item contains an embedded Object, which will be
* recursively copied. Otherwise the Object must be a Group, so the Group will
* be copied, and the list of Objects it contains will be recursively copied.
*/
static SV *
copy_xs_ea_object(SV *src_sv)
{
xs_ea_object_t *src, *dst;
SV *dst_sv, *dst_rv;
/* Get the source xs_ea_object_t and make a new one. */
PERL_ASSERT(src_sv != NULL);
src_sv = SvRV(src_sv);
PERL_ASSERT(src_sv != NULL);
src = INT2PTR(xs_ea_object_t *, SvIV(src_sv));
PERL_ASSERT(src != NULL);
New(0, dst, 1, xs_ea_object_t);
dst->flags = src->flags;
/* If the Object is a plain Item only the ea_obj part needs copying. */
if (IS_PLAIN_ITEM(src)) {
dst->ea_obj = ea_copy_object_tree(src->ea_obj);
PERL_ASSERT(dst->ea_obj != NULL);
dst->perl_obj = NULL;
/*
* Otherwise if it is an Item with a perl_obj part, it means that it
* must be an Item containing an unpacked nested Object. In this case
* the nested Object can be copied by a recursive call.
*/
} else if (IS_EMBED_ITEM(src)) {
dst->ea_obj = ea_copy_object(src->ea_obj);
PERL_ASSERT(dst->ea_obj != NULL);
dst->perl_obj = copy_xs_ea_object(src->perl_obj);
/*
* If we get here it must be a Group, so perl_obj will point to a tied
* AV. We therefore copy the exacct part then create a new tied array
* and recursively copy each Item individually.
*/
} else {
MAGIC *mg;
AV *src_av, *dst_av, *tied_av;
SV *sv;
int i, len;
/* Copy the exacct part of the Group. */
dst->ea_obj = ea_copy_object(src->ea_obj);
PERL_ASSERT(dst->ea_obj != NULL);
/* Find the AV underlying the tie. */
mg = mg_find(SvRV(src->perl_obj), 'P');
PERL_ASSERT(mg != NULL);
src_av = (AV *)SvRV(mg->mg_obj);
PERL_ASSERT(src_av != NULL);
/* Create a new AV and copy across into it. */
dst_av = newAV();
len = av_len(src_av) + 1;
av_extend(dst_av, len);
for (i = 0; i < len; i++) {
SV **svp;
/* undef elements don't need copying. */
if ((svp = av_fetch(src_av, i, FALSE)) != NULL) {
sv = copy_xs_ea_object(*svp);
if (av_store(dst_av, i, sv) == NULL) {
SvREFCNT_dec(sv);
}
}
}
/* Create a new AV and tie the filled AV to it. */
sv = newRV_noinc((SV *)dst_av);
sv_bless(sv, Sun_Solaris_Exacct_Object__Array_stash);
tied_av = newAV();
sv_magic((SV *)tied_av, sv, 'P', Nullch, 0);
SvREFCNT_dec(sv);
dst->perl_obj = newRV_noinc((SV *)tied_av);
}
/* Wrap the new xs_ea_object_t in a blessed RV and return it. */
dst_sv = newSViv(PTR2IV(dst));
dst_rv = newRV_noinc(dst_sv);
sv_bless(dst_rv, SvSTASH(src_sv));
SvREADONLY_on(dst_sv);
return (dst_rv);
}
/*
* If an ea_xs_object_t only has the ea_obj part populated, create the
* corresponding perl_obj part. For plain Items this is a no-op. If the
* object is embedded, the embedded part will be unpacked and stored in the
* perl part. If the object is a Group, the linked list of Items will be
* wrapped in the corresponding perl structure and stored in a tied perl array.
*/
static int
inflate_xs_ea_object(xs_ea_object_t *xs_obj)
{
ea_object_t *ea_obj;
/* Check there is not already a perl_obj part. */
PERL_ASSERT(xs_obj != NULL);
PERL_ASSERT(xs_obj->perl_obj == NULL);
/* Deal with Items containing embedded Objects. */
if (IS_EMBED_ITEM(xs_obj)) {
/* unpack & wrap in an xs_ea_object_t. */
if (ea_unpack_object(&ea_obj, EUP_ALLOC,
xs_obj->ea_obj->eo_item.ei_object,
xs_obj->ea_obj->eo_item.ei_size) == -1) {
return (0);
}
xs_obj->perl_obj = new_xs_ea_object(ea_obj);
/* Deal with Groups. */
} else if (IS_GROUP(xs_obj)) {
int i, len;
AV *av, *tied_av;
SV *rv, *sv;
/* Create a new array. */
av = newAV();
ea_obj = xs_obj->ea_obj;
len = ea_obj->eo_group.eg_nobjs;
ea_obj = ea_obj->eo_group.eg_objs;
/* Copy each object from the old array into the new array. */
for (i = 0; i < len; i++) {
rv = new_xs_ea_object(ea_obj);
if (av_store(av, i, rv) == NULL) {
SvREFCNT_dec(rv);
}
ea_obj = ea_obj->eo_next;
}
/* Create a new AV and tie the filled AV to it. */
rv = newRV_noinc((SV *)av);
sv_bless(rv, Sun_Solaris_Exacct_Object__Array_stash);
tied_av = newAV();
sv_magic((SV *)tied_av, rv, 'P', Nullch, 0);
SvREFCNT_dec(rv);
xs_obj->perl_obj = newRV_noinc((SV *)tied_av);
}
return (1);
}
/*
* The XS code exported to perl is below here. Note that the XS preprocessor
* has its own commenting syntax, so all comments from this point on are in
* that form.
*/
MODULE = Sun::Solaris::Exacct::Object PACKAGE = Sun::Solaris::Exacct::Object
PROTOTYPES: ENABLE
#
# Define the stash pointers if required and create and populate @_Constants.
#
BOOT:
{
init_stashes();
define_constants(PKGBASE "::Object", constants);
}
#
# Return a dual-typed SV containing the type of the object.
Object/Object.xs view on Meta::CPAN
SV *catalog;
SV *value;
PREINIT:
ea_object_t *ea_obj;
HV *stash;
CODE:
/* Create a new xs_ea_object_t and subsiduary structures. */
New(0, RETVAL, 1, xs_ea_object_t);
RETVAL->ea_obj = ea_obj = ea_alloc(sizeof (ea_object_t));
bzero(ea_obj, sizeof (*ea_obj));
ea_obj->eo_type = EO_ITEM;
ea_obj->eo_catalog = catalog_value(catalog);
INIT_PLAIN_ITEM_FLAGS(RETVAL);
RETVAL->perl_obj = NULL;
/* Assign the Item's value. */
switch (ea_obj->eo_catalog & EXT_TYPE_MASK) {
case EXT_UINT8:
ea_obj->eo_item.ei_uint8 = SvIV(value);
ea_obj->eo_item.ei_size = sizeof (uint8_t);
break;
case EXT_UINT16:
ea_obj->eo_item.ei_uint16 = SvIV(value);
ea_obj->eo_item.ei_size = sizeof (uint16_t);
break;
case EXT_UINT32:
ea_obj->eo_item.ei_uint32 = SvIV(value);
ea_obj->eo_item.ei_size = sizeof (uint32_t);
break;
case EXT_UINT64:
ea_obj->eo_item.ei_uint64 = SvIV(value);
ea_obj->eo_item.ei_size = sizeof (uint64_t);
break;
case EXT_DOUBLE:
ea_obj->eo_item.ei_double = SvNV(value);
ea_obj->eo_item.ei_size = sizeof (double);
break;
case EXT_STRING:
ea_obj->eo_item.ei_string = ea_strdup(SvPV_nolen(value));
ea_obj->eo_item.ei_size = SvCUR(value) + 1;
break;
case EXT_RAW:
ea_obj->eo_item.ei_size = SvCUR(value);
ea_obj->eo_item.ei_raw = ea_alloc(ea_obj->eo_item.ei_size);
bcopy(SvPV_nolen(value), ea_obj->eo_item.ei_raw,
(size_t)ea_obj->eo_item.ei_size);
break;
case EXT_EXACCT_OBJECT:
/*
* The ea_obj part is initially empty, and will be populated
* from the perl_obj part when required.
*/
stash = SvROK(value) ? SvSTASH(SvRV(value)) : NULL;
if (stash != Sun_Solaris_Exacct_Object_Item_stash &&
stash != Sun_Solaris_Exacct_Object_Group_stash) {
croak("value is not of type " PKGBASE "::Object");
}
RETVAL->perl_obj = copy_xs_ea_object(value);
ea_obj->eo_item.ei_object = NULL;
ea_obj->eo_item.ei_size = 0;
INIT_EMBED_ITEM_FLAGS(RETVAL);
break;
/*
* EXT_NONE is an invalid type,
* EXT_GROUP is created by the Group subclass constructor.
*/
case EXT_NONE:
case EXT_GROUP:
default:
ea_free(RETVAL->ea_obj, sizeof (RETVAL->ea_obj));
Safefree(RETVAL);
croak("Invalid object type");
break;
}
OUTPUT:
RETVAL
MODULE = Sun::Solaris::Exacct::Object PACKAGE = Sun::Solaris::Exacct::Object::Group
PROTOTYPES: ENABLE
xs_ea_object_t *
new(class, catalog, ...)
char *class;
SV *catalog;
PREINIT:
ea_catalog_t tag;
ea_object_t *ea_obj;
AV *tied_av, *av;
SV *sv, *rv;
int i;
CODE:
tag = catalog_value(catalog);
if ((tag & EXT_TYPE_MASK) != EXT_GROUP) {
croak("Invalid object type");
}
/* Create a new xs_ea_object_t and subsiduary structures. */
New(0, RETVAL, 1, xs_ea_object_t);
RETVAL->ea_obj = ea_obj = ea_alloc(sizeof (ea_object_t));
bzero(ea_obj, sizeof (*ea_obj));
ea_obj->eo_type = EO_GROUP;
ea_obj->eo_catalog = tag;
INIT_GROUP_FLAGS(RETVAL);
RETVAL->perl_obj = NULL;
/* Create a new AV and copy in all the passed Items. */
av = newAV();
av_extend(av, items - 2);
for (i = 2; i < items; i++) {
HV *stash;
stash = SvROK(ST(i)) ? SvSTASH(SvRV(ST(i))) : NULL;
if (stash != Sun_Solaris_Exacct_Object_Item_stash &&
stash != Sun_Solaris_Exacct_Object_Group_stash) {
croak("item is not of type " PKGBASE "::Object");
}
av_store(av, i - 2, copy_xs_ea_object(ST(i)));
}
/* Bless the copied AV and tie it to a new AV */
rv = newRV_noinc((SV *)av);
sv_bless(rv, Sun_Solaris_Exacct_Object__Array_stash);
( run in 0.662 second using v1.01-cache-2.11-cpan-71847e10f99 )