Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: de6a984c5e
Fetching contributors…

Cannot retrieve contributors at this time

599 lines (417 sloc) 13.989 kb
/*
Copyright (C) 2001-2011, Parrot Foundation.
=head1 NAME
src/pmc/packfile.pmc - Packfile PMC
=head1 DESCRIPTION
This class implements a Packfile object, as specified in PDD13. This object is
the top level parser and serializer for *.pbc files.
=head2 Methods
=over 4
=cut
*/
#include "pmc/pmc_packfiledirectory.h"
typedef enum {
attr_wordsize,
attr_byteorder,
attr_fptype,
attr_version_major,
attr_version_minor,
attr_version_patch,
attr_bytecode_major,
attr_bytecode_minor,
attr_uuid_type,
attr_NONE = -1
} AttrEnumPackfile;
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
static void copy_packfile_header(PARROT_INTERP,
ARGMOD(PMC *self),
ARGIN(PackFile *pf))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(*self);
static AttrEnumPackfile getAttrEnum(PARROT_INTERP,
ARGIN(const STRING *name))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
#define ASSERT_ARGS_copy_packfile_header __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(pf))
#define ASSERT_ARGS_getAttrEnum __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(name))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
/*
=item C<static void copy_packfile_header(PARROT_INTERP, PMC *self, PackFile
*pf)>
Copy attributes from PackFile* to Packfile PMC.
=cut
*/
static void
copy_packfile_header(PARROT_INTERP, ARGMOD(PMC *self), ARGIN(PackFile *pf))
{
ASSERT_ARGS(copy_packfile_header)
Parrot_Packfile_attributes * const attrs = PARROT_PACKFILE(self);
attrs->wordsize = pf->header->wordsize;
attrs->byteorder = pf->header->byteorder;
attrs->fptype = pf->header->floattype;
attrs->version_major = pf->header->major;
attrs->version_minor = pf->header->minor;
attrs->version_patch = pf->header->patch;
attrs->bytecode_major = pf->header->bc_major;
attrs->bytecode_minor = pf->header->bc_minor;
attrs->uuid_type = pf->header->uuid_type;
attrs->uuid = Parrot_str_new(interp, (char*)pf->header->uuid_data,
pf->header->uuid_size);
}
pmclass Packfile auto_attrs {
ATTR INTVAL wordsize;
ATTR INTVAL byteorder;
ATTR INTVAL fptype;
ATTR INTVAL version_major;
ATTR INTVAL version_minor;
ATTR INTVAL version_patch;
ATTR INTVAL bytecode_major;
ATTR INTVAL bytecode_minor;
ATTR INTVAL uuid_type;
ATTR STRING *uuid;
ATTR PMC *directory;
/*
=item C<void init()>
Initialize the structure. (Create a blank PackFile object.)
=item C<VTABLE void init_pmc(view)>
Create a new PackFile from an existing PackFileView.
=cut
*/
VTABLE void init() {
Parrot_Packfile_attributes * const attrs =
PMC_data_typed(SELF, Parrot_Packfile_attributes*);
PackFile *pf;
/* copy_packfile_header can trigger GC. Set custom_mark flag early */
PObj_custom_mark_SET(SELF);
attrs->uuid = CONST_STRING(INTERP, "");
attrs->directory = Parrot_pmc_new(INTERP, enum_class_PackfileDirectory);
/* Create dummy PackFile and copy default attributes to self */
pf = PackFile_new(INTERP, 0);
copy_packfile_header(INTERP, SELF, pf);
PackFile_destroy(INTERP, pf);
}
VTABLE void init_pmc(PMC *view) {
VTABLE_init(interp, SELF);
VTABLE_set_pointer(interp, SELF, VTABLE_get_pointer(interp, view));
}
/*
=item C<void mark()>
Marks the Packfile as alive.
=cut
*/
VTABLE void mark() {
Parrot_Packfile_attributes * const attrs = PARROT_PACKFILE(SELF);
Parrot_gc_mark_STRING_alive(INTERP, attrs->uuid);
Parrot_gc_mark_PMC_alive(INTERP, attrs->directory);
}
/*
=item C<STRING *get_string()>
Return raw serialized PBC file data.
=cut
Implementation note: all hard stuff done by PackfileDirectory.
*/
VTABLE STRING *get_string() {
STRING *str;
const Parrot_Packfile_attributes * const attrs = PARROT_PACKFILE(SELF);
PackFile * const pf =
(PackFile*)VTABLE_get_pointer(INTERP, attrs->directory);
/* Copy related attributes to header */
pf->header->major = attrs->version_major;
pf->header->minor = attrs->version_minor;
pf->header->patch = attrs->version_patch;
pf->header->uuid_type = attrs->uuid_type;
str = Parrot_pf_serialize(INTERP, pf);
PackFile_destroy(INTERP, pf);
return str;
}
/*
=item C<void set_string_native(STRING *str)>
Parse raw serialized PBC file data into the Packfile data structure.
=cut
Implementation note: taken from the bottom end of Parrot_pbc_read().
*/
VTABLE void set_string_native(STRING *str) {
Parrot_Packfile_attributes * const attrs = PARROT_PACKFILE(SELF);
PackFile * const pf = Parrot_pf_deserialize(INTERP, str);
/* Disable GC during copy data into internal structures. */
Parrot_block_GC_mark(INTERP);
/* Copy values from PackFile header to own attributes */
copy_packfile_header(INTERP, SELF, pf);
VTABLE_set_pointer(INTERP, attrs->directory, &pf->directory);
Parrot_unblock_GC_mark(INTERP);
/* XXX memory leak
* Destroying the packfile here frees segments that may still have live references
* (eg: sub->seg)
* A memory leak is better than an invalid memory access
*/
#if 0
PackFile_destroy(INTERP, pf);
#endif
}
/*
=item C<void set_pointer(void *ptr)>
Set a raw PackFile* pointer to this Packfile PMC
=cut
*/
VTABLE void set_pointer(void * ptr) {
Parrot_Packfile_attributes * const attrs = PARROT_PACKFILE(SELF);
PackFile * const pf = (PackFile *)ptr;
Parrot_block_GC_mark(INTERP);
copy_packfile_header(INTERP, SELF, pf);
VTABLE_set_pointer(INTERP, attrs->directory, &pf->directory);
Parrot_unblock_GC_mark(INTERP);
}
/*
=item C<INTVAL get_integer_keyed_str(STRING *key)>
Fetch an integer keyed value from the packfile object. Valid keys are:
=over 4
=item wordsize
=item byteorder
=item fptype
=item version_major
=item version_minor
=item version_patch
=item bytecode_major
=item bytecode_minor
=item uuid_type
=back
=cut
*/
VTABLE INTVAL get_integer_keyed_str(STRING *key) {
const Parrot_Packfile_attributes * const attrs = PARROT_PACKFILE(SELF);
INTVAL result;
switch (getAttrEnum(INTERP, key)) {
case attr_wordsize:
result = attrs->wordsize;
break;
case attr_byteorder:
result = attrs->byteorder;
break;
case attr_fptype:
result = attrs->fptype;
break;
case attr_version_major:
result = attrs->version_major;
break;
case attr_version_minor:
result = attrs->version_minor;
break;
case attr_version_patch:
result = attrs->version_patch;
break;
case attr_bytecode_major:
result = attrs->bytecode_major;
break;
case attr_bytecode_minor:
result = attrs->bytecode_minor;
break;
case attr_uuid_type:
result = attrs->uuid_type;
break;
default:
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_KEY_NOT_FOUND,
"Packfile: No such integer key \"%Ss\"", key);
}
return result;
}
/*
=item C<STRING *get_string_keyed_str(STRING *key)>
Fetch a string keyed value from the packfile object. Valid keys are:
=over 4
=item uuid
=back
=cut
*/
VTABLE STRING *get_string_keyed_str(STRING *key) {
if (STRING_equal(INTERP, key, CONST_STRING(INTERP, "uuid")))
return PARROT_PACKFILE(SELF)->uuid;
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_KEY_NOT_FOUND,
"Packfile: No such string key \"%Ss\"", key);
}
/*
=item C<INTVAL get_integer_keyed(PMC *key)>
Fetch a keyed integer value from the packfile object. Dispatches to
get_integer_keyed_str.
=cut
*/
VTABLE INTVAL get_integer_keyed(PMC *key) {
STRING * const s = VTABLE_get_string(INTERP, key);
return SELF.get_integer_keyed_str(s);
}
/*
=item C<STRING *get_string_keyed(PMC *key)>
Fetch a keyed string value from the packfile object. Dispatches to
get_string_keyed_str.
=cut
*/
VTABLE STRING *get_string_keyed(PMC *key) {
STRING * const s = VTABLE_get_string(INTERP, key);
return SELF.get_string_keyed_str(s);
}
/*
=item C<void set_integer_keyed_str(STRING *key, INTVAL value)>
Set an integer keyed value to the specified value. Valid keys are:
=over 4
=item version_major
=item version_minor
=item version_patch
=item uuid_type
=back
=cut
*/
VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
Parrot_Packfile_attributes * const attrs = PARROT_PACKFILE(SELF);
switch (getAttrEnum(INTERP, key)) {
case attr_version_major:
attrs->version_major = value;
break;
case attr_version_minor:
attrs->version_minor = value;
break;
case attr_version_patch:
attrs->version_patch = value;
break;
case attr_uuid_type:
attrs->uuid_type = value;
break;
default:
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_KEY_NOT_FOUND,
"Packfile: No such integer key \"%Ss\"", key);
}
}
/*
=item C<void set_integer_keyed(PMC *key, INTVALval)>
Set a keyed integer value in the packfile object. Dispatches to
set_integer_keyed_str.
=cut
*/
VTABLE void set_integer_keyed(PMC *key, INTVAL val) {
STRING * const s = VTABLE_get_string(INTERP, key);
SELF.set_integer_keyed_str(s, val);
}
/*
=item * C<get_string_keyed_str> (v-table)
Used to get data about fields in the header that have a string value. Valid
keys are:
=over 4
=item uuid
=back
=cut
*/
VTABLE void set_string_keyed_str(STRING *key, STRING *value) {
if (STRING_equal(INTERP, key, CONST_STRING(INTERP, "uuid"))) {
PARROT_PACKFILE(SELF)->uuid = value;
return;
}
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_KEY_NOT_FOUND,
"Packfile: No such string key \"%Ss\"", key);
}
/*
=item C<void set_string_keyed(PMC *key, STRING *val)>
Set a keyed string value in the packfile object. Dispatches to
set_string_keyed_str.
=cut
*/
VTABLE void set_string_keyed(PMC *key, STRING *val) {
STRING * const s = VTABLE_get_string(INTERP, key);
SELF.set_string_keyed_str(s, val);
}
/*
=item C<STRING * pack()>
Return raw serialized PBC file data. Synonym for get_string.
=cut
*/
METHOD pack() {
STRING * const ret = SELF.get_string();
RETURN(STRING * ret);
}
/*
=item C<void unpack(STRING *data)>
Parse raw serialized PBC file data into the Packfile data structure.
Synonym for set_string.
=cut
*/
METHOD unpack(STRING *str) {
SELF.set_string_native(str);
}
/*
=item C<PMC *get_directory()>
Fetch the PackfileDirectory PMC that represents the directory segment at the
start of the packfile.
=cut
*/
METHOD get_directory() {
PMC * const dir = PARROT_PACKFILE(SELF)->directory;
RETURN(PMC *dir);
}
/*
=item C<PMC *view()>
Get a PackfileView for the current packfile. PackfileView is a read-only
wrapper around a static packfile structure. This method creates a fresh copy
of the packfile structure and assigns that copy to the new PackfileView PMC.
=cut
*/
METHOD view() {
const Parrot_Packfile_attributes * const attrs = PARROT_PACKFILE(SELF);
PackFile * const pf =
(PackFile*)VTABLE_get_pointer(INTERP, attrs->directory);
PMC * const view = Parrot_pf_get_packfile_pmc(INTERP, pf, STRINGNULL);
RETURN(PMC * view);
}
}
/*
=back
=cut
=head2 Auxliary functions
=over 4
=item C<static AttrEnumPackfile getAttrEnum(PARROT_INTERP, const STRING *name)>
Gets an enumerated value corresponding to the attribute with that name.
=cut
*/
static AttrEnumPackfile
getAttrEnum(PARROT_INTERP, ARGIN(const STRING *name))
{
ASSERT_ARGS(getAttrEnum)
AttrEnumPackfile r;
if (STRING_equal(interp, name, CONST_STRING(interp, "wordsize")))
r = attr_wordsize;
else if (STRING_equal(interp, name, CONST_STRING(interp, "byteorder")))
r = attr_byteorder;
else if (STRING_equal(interp, name, CONST_STRING(interp, "fptype")))
r = attr_fptype;
else if (STRING_equal(interp, name, CONST_STRING(interp, "version_major")))
r = attr_version_major;
else if (STRING_equal(interp, name, CONST_STRING(interp, "version_minor")))
r = attr_version_minor;
else if (STRING_equal(interp, name, CONST_STRING(interp, "version_patch")))
r = attr_version_patch;
else if (STRING_equal(interp, name, CONST_STRING(interp, "bytecode_major")))
r = attr_bytecode_major;
else if (STRING_equal(interp, name, CONST_STRING(interp, "bytecode_minor")))
r = attr_bytecode_minor;
else if (STRING_equal(interp, name, CONST_STRING(interp, "uuid_type")))
r = attr_uuid_type;
else
r = attr_NONE;
return r;
}
/*
=back
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/
Jump to Line
Something went wrong with that request. Please try again.