SGML-SPGroveBuilder
view release on metacpan or search on metacpan
SPGroveNew.cc view on Meta::CPAN
//
void
SPGrove::startElement(const StartElementEvent &event)
{
flushData();
SV *element[3];
// Create empty array for contents
AV *contents = newAV();
element[0] = newRV_noinc((SV*)contents);
// Name
element[1] = newSVpv(as_string(event.gi), event.gi.len);
// Attributes
HV *attributes = (HV*)&sv_undef;
size_t nAttributes = event.nAttributes;
if (nAttributes > 0) {
// XXX we can optimize by using a C array and av_make instead of push
const Attribute *att_ptr = event.attributes;
while (nAttributes-- > 0) {
switch (att_ptr->type) {
case Attribute::implied:
break; // ignored
case Attribute::tokenized:
{
if (attributes == (HV*)&sv_undef) {
attributes = newHV();
}
if (att_ptr->nEntities != 0) {
AV *att_data = newAV();
size_t nEntities = att_ptr->nEntities;
const SGMLApplication::Entity *entities = att_ptr->entities;
while (nEntities-- > 0) {
SV *entity_ref = entity (entities);
SvREFCNT_inc (entity_ref);
av_push (att_data, entity_ref);
entities ++;
}
hv_store (attributes,
as_string(att_ptr->name), att_ptr->name.len,
newRV_noinc((SV*)att_data), 0);
} else if (att_ptr->notation.name.len > 0) {
SV *notation_ref = notation(&att_ptr->notation);
SvREFCNT_inc (notation_ref);
hv_store (attributes,
as_string(att_ptr->name), att_ptr->name.len,
notation_ref, 0);
} else {
SV *token = newSVpv(as_string(att_ptr->tokens), att_ptr->tokens.len);
hv_store (attributes,
as_string(att_ptr->name), att_ptr->name.len,
token, 0);
}
}
break;
case Attribute::cdata:
{
AV *att_data = newAV();
size_t nCdataChunks = att_ptr->nCdataChunks;
const SGMLApplication::Attribute::CdataChunk *cdataChunk
= att_ptr->cdataChunks;
if (attributes == (HV*)&sv_undef) {
attributes = newHV();
}
// XXX we can optimize by using a C array and av_make instead of push
while (nCdataChunks-- > 0) {
SV *data = NULL;
if (cdataChunk->isSdata) {
SV *sdata_a[2];
sdata_a[0] = newSVpv(as_string(cdataChunk->data),
cdataChunk->data.len);
sdata_a[1] = newSVpv(as_string(cdataChunk->entityName),
cdataChunk->entityName.len);
AV *sdata = av_make(2, &sdata_a[0]);
SvREFCNT_dec (sdata_a[0]);
SvREFCNT_dec (sdata_a[1]);
data = newRV_noinc((SV*)sdata);
sv_bless (data, sdata_stash_);
} else if (!cdataChunk->isNonSgml) {
data = newSVpv(as_string(cdataChunk->data), cdataChunk->data.len);
} else {
// XXX we need to do better than this
fprintf (stderr, "SPGroveNew: isNonSGML in cdata attribute\n");
}
if (data != NULL) {
av_push (att_data, data);
}
cdataChunk ++;
}
hv_store (attributes,
as_string(att_ptr->name), att_ptr->name.len,
newRV_noinc((SV*)att_data), 0);
}
break;
default: {
// XXX this is a CANT_HAPPEN
av_push(errors_, newSVpv("SPGroveNew: invalid attribute type", 0));
break;
}
}
att_ptr ++;
}
}
// finish off adding the attributes to the element
if (attributes == (HV*)&sv_undef) {
element[2] = &sv_undef;
} else {
element[2] = newRV_noinc((SV*)attributes);
}
// create a reference so we can bless it and pass it around
SV *element_ref = newRV_noinc((SV*)av_make(3, &element[0]));
SvREFCNT_dec (element[0]);
SvREFCNT_dec (element[1]);
if (element[2] != &sv_undef) {
SvREFCNT_dec (element[2]);
}
sv_bless (element_ref, element_stash_);
av_push (contents_, element_ref);
av_push (stack_, (SV*)contents_);
// cache the contents array
contents_ = contents;
}
//
// `endElement' is called at the closing of each element in the
// instance. `endElement' pulls the parent element off the stack and
// copies it's contents to the `contents_' cache
//
void
SPGrove::endElement(const EndElementEvent &)
{
flushData();
contents_ = (AV*)av_pop(stack_);
}
//
// `data' is called when ordinary instance data comes across
//
// XXX we could provide an option for concatenation
void
SPGrove::data(const DataEvent &event)
{
SPGroveNew.cc view on Meta::CPAN
av_push(contents_, pi_ref);
}
//
// `externalDataEntity'
//
void
SPGrove::externalDataEntityRef(const ExternalDataEntityRefEvent &event)
{
flushData();
SV *entity_ref = entity(&event.entity);
SvREFCNT_inc (entity_ref);
av_push(contents_, entity_ref);
}
//
// `subdocEntityRef'
//
void SPGrove::subdocEntityRef(const SubdocEntityRefEvent &event)
{
flushData();
SV *entity_ref = entity(&event.entity);
SvREFCNT_inc (entity_ref);
av_push(contents_, entity_ref);
}
//
// `nonSgmlChar'
//
void SPGrove::nonSgmlChar(const NonSgmlCharEvent &event)
{
flushData();
fprintf (stderr, "SPGroveNew: nonSgmlChar not handled\n");
}
//
// `error' is called when an error is encountered during the parse.
//
void SPGrove::error(const ErrorEvent &event) {
av_push(errors_, newSVpv(as_string(event.message), event.message.len));
}
//
// `entity' returns an entity definition, creating it if necessary
//
SV *
SPGrove::entity (const SGMLApplication::Entity *entity)
{
char *name = as_string(entity->name);
SV **entity_def = hv_fetch(entities_, name, entity->name.len, 0);
if (!entity_def) {
HV *new_entity = newHV();
hv_store(new_entity, "name", 4, newSVpv(name, entity->name.len), 0);
char *type = 0;
HV *stash;
switch (entity->dataType) {
case Entity::cdata: type = "CDATA"; stash = extentity_stash_; break;
case Entity::sdata: type = "SDATA"; stash = extentity_stash_; break;
case Entity::ndata: type = "NDATA"; stash = extentity_stash_; break;
case Entity::subdoc: stash = subdocentity_stash_; break;
default: {
av_push(errors_, newSVpv("SPGroveNew: data type not handled", 0));
}
}
if (type) {
hv_store(new_entity, "type", 4, newSVpv(type, 5), 0);
}
if (entity->isInternal) {
hv_store(new_entity, "data", 4,
newSVpv(as_string(entity->text), entity->text.len), 0);
stash = entity_stash_;
} else {
store_external_id (new_entity, &entity->externalId);
// XXX attributes
if (entity->notation.name.len > 0) {
SV *notation_ref = notation(&entity->notation);
SvREFCNT_inc (notation_ref);
hv_store(new_entity, "notation", 8,
notation_ref, 0);
}
}
SV *entity_ref = newRV_noinc((SV*)new_entity);
sv_bless (entity_ref, stash);
name = as_string(entity->name); // again since it was overwritten
entity_def = hv_store (entities_, name, entity->name.len, entity_ref, 0);
}
return (*entity_def);
}
//
// `notation' returns a notation definition, creating it if necessary
//
SV *
SPGrove::notation (const SGMLApplication::Notation *notation)
{
char *name = as_string(notation->name);
SV **notation_def = hv_fetch(notations_, name, notation->name.len, 0);
if (!notation_def) {
HV *new_notation = newHV();
hv_store(new_notation, "name", 4, newSVpv(name, notation->name.len), 0);
store_external_id (new_notation, ¬ation->externalId);
SV *notation_ref = newRV_noinc((SV*)new_notation);
sv_bless (notation_ref, notation_stash_);
name = as_string(notation->name); // again since it was overwritten
notation_def = hv_store (notations_, name, notation->name.len, notation_ref, 0);
}
return (*notation_def);
}
//
// `store_external_id' stores external ID values in `hash'
( run in 2.323 seconds using v1.01-cache-2.11-cpan-995e09ba956 )