
Contents of /Public_Parser_XML2-1.42/SAX.cmod:
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: SAX.cmod,v 1.11 2005-12-28 18:49:20 hww3 Exp $
*/
/*
* File licensing and authorship information block.
*
* Version: MPL 1.1/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Initial Developer of the Original Code is
*
* Bill Welliver <hww3@riverweb.com>
*
* Portions created by the Initial Developer are Copyright (C) Bill Welliver
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of the LGPL, and not to allow others to use your version
* of this file under the terms of the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL or the LGPL.
*
* Significant Contributors to this file are:
*
*
*/
#include "xml2.h"
/*! @module Public
*/
/*! @module Parser
*/
/*! @module XML2
*/
/*! @class SAX
*!
*! a SAX v1/v2 parser featuring both pull and push (chunked) parsing.
*!
*/
PIKECLASS SAX
{
CVAR SAX_OBJECT_DATA * object_data;
void PSAX_plain_callback(int callback_id, void * data)
{
int z = 0;
if(ITEM(THIS->object_data->handlers)[callback_id].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int retval;
o = ITEM(THIS->object_data->handlers)[callback_id].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size);
pop_stack();
}
}
void PSAX_string_len_callback(int cb_type, void * ctx, const xmlChar * ch, int len)
{
if(ITEM(THIS->object_data->handlers)[cb_type].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[cb_type].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_string(make_shared_binary_string((char *) ch, len));
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 1);
pop_stack();
}
}
int PSAX_plain_int_callback(int callback_id, void * data)
{
int retval;
int z = 0;
if(ITEM(THIS->object_data->handlers)[callback_id].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
o = ITEM(THIS->object_data->handlers)[callback_id].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size);
retval = Pike_sp[0-1].u.integer;
pop_stack();
return retval;
}
return 0;
}
xmlEntityPtr my_getEntity(void * ctx, const xmlChar * name)
{
if(ITEM(THIS->object_data->handlers)[CB_GETENTITY].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
xmlEntityPtr ent;
o = ITEM(THIS->object_data->handlers)[CB_GETENTITY].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 1);
if(Pike_sp[0-1].type == T_STRING)
{
printf("got value: %s\n", Pike_sp[0-1].u.string->str);
ent = xmlMalloc(sizeof(xmlEntity));
if(ent == NULL) printf("unable to allocate entity storage.\n");
memset(ent, 0, sizeof(xmlEntity));
ent->type = XML_ENTITY_DECL;
ent->etype = XML_ENTITY_NODE;
ent->name = xmlStrdup(name);
ent->content = xmlStrdup(Pike_sp[0-1].u.string->str);
pop_stack();
return ent;
}
else if(Pike_sp[0-1].type == T_INT && Pike_sp[0-1].u.integer == 0)
{
pop_stack();
return NULL;
}
else
{
pop_stack();
Pike_error("bad return value from get_entity callback: expected string.\n");
}
}
pop_stack();
return NULL;
}
void my_serror(void * ctx, xmlErrorPtr error)
{
if(ITEM(THIS->object_data->handlers)[CB_SERROR].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_SERROR].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text("domain");
push_int(error->domain);
push_text("code");
push_int(error->code);
push_text("message");
push_text((char *)error->message);
push_text("level");
push_int(error->level);
push_text("line");
push_int(error->line);
push_text("column");
push_int(error->int2);
f_aggregate_mapping(12);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 1);
pop_stack();
}
}
xmlEntityPtr my_getParameterEntity(void * ctx, const xmlChar * name)
{
if(ITEM(THIS->object_data->handlers)[CB_GETPARAMETERENTITY].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
xmlParserInputPtr rs = NULL;
o = ITEM(THIS->object_data->handlers)[CB_GETPARAMETERENTITY].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 1);
// check that we've returned a string.
if(Pike_sp[0-1].type == PIKE_T_STRING)
{
char * r;
if((Pike_sp[0-1].u.string->str)[-1] != '\0')
r = malloc( Pike_sp[0-1].u.string->len + 1);
else
r = malloc( Pike_sp[0-1].u.string->len);
#if defined(HAVE_STRLCPY)
r=strlcpy(r, Pike_sp[0-1].u.string->str, Pike_sp[0-1].u.string->len);
#elif defined(HAVE_MEMCPY)
r=memcpy(r, Pike_sp[0-1].u.string->str, Pike_sp[0-1].u.string->len);
#else
#error "You don't have memcpy!"
#endif
if((Pike_sp[0-1].u.string->str)[-1] != '\0')
r[-1]='\0';
rs = xmlNewStringInputStream(ctx, (xmlChar *)r);
pop_stack();
return rs;
}
else if(Pike_sp[0-1].type == PIKE_T_INT && Pike_sp[0-1].u.integer == 0)
{
rs = xmlNewStringInputStream(ctx, (xmlChar *)'0');
pop_stack();
return rs;
}
else
{
pop_stack();
Pike_error("Return value expected to be of type string.\n");
}
}
}
xmlParserInputPtr my_resolveEntity(void * ctx, const xmlChar * publicId,
const xmlChar * systemId)
{
if(ITEM(THIS->object_data->handlers)[CB_RESOLVEENTITY].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
xmlParserInputPtr rs = NULL;
o = ITEM(THIS->object_data->handlers)[CB_RESOLVEENTITY].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)publicId);
push_text((char *)systemId);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 2);
// check that we've returned a string.
if(Pike_sp[0-1].type == PIKE_T_STRING)
{
char * r;
if((Pike_sp[0-1].u.string->str)[-1] != '\0')
r = malloc( Pike_sp[0-1].u.string->len + 1);
else
r = malloc( Pike_sp[0-1].u.string->len);
r=memcpy(r, Pike_sp[0-1].u.string->str, Pike_sp[0-1].u.string->len);
if((Pike_sp[0-1].u.string->str)[-1] != '\0')
r[-1]='\0';
rs = xmlNewStringInputStream(ctx, (xmlChar *)r);
pop_stack();
return rs;
}
else if(Pike_sp[0-1].type == PIKE_T_INT && Pike_sp[0-1].u.integer == 0)
{
rs = xmlNewStringInputStream(ctx, (xmlChar *)'0');
pop_stack();
return rs;
}
else
{
pop_stack();
Pike_error("Return value expected to be of type string.\n");
}
}
}
void my_entityDecl(void * ctx, const xmlChar * name, int type, const xmlChar * publicId, const xmlChar * systemId, xmlChar * content)
{
if(ITEM(THIS->object_data->handlers)[CB_ENTITYDECL].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_ENTITYDECL].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
push_int(type);
push_text((char *)publicId);
push_text((char *)systemId);
push_text((char *)content);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 5);
pop_stack();
}
}
void my_elementDecl(void * ctx, const xmlChar * name, int type, xmlElementContentPtr content)
{
if(ITEM(THIS->object_data->handlers)[CB_ELEMENTDECL].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_ELEMENTDECL].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
push_int(type);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 2);
pop_stack();
}
}
void my_unparsedEntityDecl(void * ctx, const xmlChar * name, const xmlChar * publicId, const xmlChar * systemId, const xmlChar * notationName)
{
if(ITEM(THIS->object_data->handlers)[CB_UNPARSEDENTITYDECL].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_UNPARSEDENTITYDECL].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
push_text((char *)publicId);
push_text((char *)systemId);
push_text((char *)notationName);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 4);
pop_stack();
}
}
void my_attributeDecl(void * ctx, const xmlChar * elem, const xmlChar* fullname, int type, int def, const xmlChar * defaultValue, xmlEnumerationPtr tree)
{
if(ITEM(THIS->object_data->handlers)[CB_ATTRIBUTEDECL].type!=PIKE_T_INT)
{
xmlEnumerationPtr p;
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_ATTRIBUTEDECL].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)elem);
push_text((char *)fullname);
push_int(type);
push_int(def);
push_text((char *)defaultValue);
if(tree!=NULL)
{
for(p = tree; p->next != NULL; p = p->next)
{
push_text((char *) p->name);
z++;
}
}
f_aggregate(z);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 5);
pop_stack();
}
}
void my_notationDecl(void * ctx, const xmlChar * name, const xmlChar * publicId, const xmlChar * systemId)
{
if(ITEM(THIS->object_data->handlers)[CB_NOTATIONDECL].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_NOTATIONDECL].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
push_text((char *)publicId);
push_text((char *)systemId);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 3);
pop_stack();
}
}
void my_internalSubset(void * ctx, const xmlChar * name, const xmlChar * ExternalID, const xmlChar * SystemID)
{
if(ITEM(THIS->object_data->handlers)[CB_INTERNALSUBSET].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_INTERNALSUBSET].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
if(ExternalID == NULL)
push_text("");
else
push_text((char *)ExternalID);
if(SystemID == NULL)
push_text("");
else
push_text((char *)SystemID);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 3);
pop_stack();
}
}
void my_externalSubset(void * ctx, const xmlChar * name, const xmlChar * ExternalID, const xmlChar * SystemID)
{
if(ITEM(THIS->object_data->handlers)[CB_EXTERNALSUBSET].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_EXTERNALSUBSET].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
push_text((char *)ExternalID);
push_text((char *)SystemID);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 3);
pop_stack();
}
}
void my_processingInstruction(void * ctx, const xmlChar * target, const xmlChar * data)
{
if(ITEM(THIS->object_data->handlers)[CB_PROCESSINGINSTRUCTION].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_PROCESSINGINSTRUCTION].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)target);
push_text((char *)data);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 2);
pop_stack();
}
}
void my_endElement(void * ctx, const xmlChar * name)
{
if(ITEM(THIS->object_data->handlers)[CB_ENDELEMENT].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_ENDELEMENT].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 1);
pop_stack();
}
}
void my_cdataBlock(void * ctx, const xmlChar * ch, int len)
{
PSAX_string_len_callback(CB_CDATABLOCK, ctx, ch, len);
}
void my_ignorableWhitespace(void * ctx, const xmlChar * ch, int len)
{
PSAX_string_len_callback(CB_IGNORABLEWHITESPACE, ctx, ch, len);
}
void my_characters(void * ctx, const xmlChar * ch, int len)
{
PSAX_string_len_callback(CB_CHARACTERS, ctx, ch, len);
}
void my_reference(void * ctx, const xmlChar * name)
{
if(ITEM(THIS->object_data->handlers)[CB_REFERENCE].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_REFERENCE].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 1);
pop_stack();
}
}
void my_comment(void * ctx, const xmlChar * value)
{
if(ITEM(THIS->object_data->handlers)[CB_COMMENT].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
int z = 0;
o = ITEM(THIS->object_data->handlers)[CB_COMMENT].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)value);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 1);
pop_stack();
}
}
void my_startElement(void * data, const xmlChar * name, const xmlChar ** atts)
{
int z = 0;
if(ITEM(THIS->object_data->handlers)[CB_STARTELEMENT].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
o = ITEM(THIS->object_data->handlers)[CB_STARTELEMENT].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)name);
if(atts!= NULL)
{
for(z=0; atts[z] != NULL; z++)
{
push_text(atts[z]);
}
}
f_aggregate_mapping(z);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 2);
pop_stack();
/* printf("finished callback.\n"); */
}
}
void my_endElementNs(void * ctx, const xmlChar * localname,
const xmlChar * prefix, const xmlChar * uri)
{
int z = 0;
if(ITEM(THIS->object_data->handlers)[CB_ENDELEMENTNS].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
o = ITEM(THIS->object_data->handlers)[CB_ENDELEMENTNS].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)localname);
if(prefix != NULL)
push_text((char *)prefix);
else
push_int(0);
if(uri != NULL)
push_text((char *)uri);
else
push_int(0);
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 3);
pop_stack();
}
}
void my_startElementNs(void * ctx, const xmlChar * localname,
const xmlChar * prefix, const xmlChar * uri,
int nb_namespaces, const xmlChar ** namespaces,
int nb_attributes, int nb_defaulted,
const xmlChar ** atts)
{
int z = 0;
int i = 0;
if(ITEM(THIS->object_data->handlers)[CB_STARTELEMENTNS].type!=PIKE_T_INT)
{
struct svalue * func;
struct array * a;
struct object * o;
o = ITEM(THIS->object_data->handlers)[CB_STARTELEMENTNS].u.object;
a = get_callback_data(o);
func = get_callback_func(o);
push_text((char *)localname);
if(prefix != NULL)
push_text((char *)prefix);
else
push_int(0);
if(uri != NULL)
push_text((char *)uri);
else
push_int(0);
if(atts!= NULL)
{
for(z=0,i=0; i< nb_attributes; i++, z=z+5)
{
push_text("name");
push_text(atts[z]);
push_text("prefix");
if(atts[z+1] != NULL)
push_text(atts[z+1]);
else push_int(0);
push_text("uri");
if(atts[z+2] != NULL)
push_text(atts[z+2]);
else push_int(0);
push_text("value");
if(atts[z+3] != NULL)
{
push_string(make_shared_binary_string((char *) atts[z+3], atts[z+4] - atts[z+3]));
}
else push_int(0);
push_text("end");
if(atts[z+4] != NULL)
{
push_text(atts[z+4]);
}
f_aggregate_mapping(10);
}
f_aggregate(i);
}
for(z = 0; z < a->size; z++)
{
push_svalue(&ITEM(a)[z]);
}
apply_svalue(func, a->size + 4);
pop_stack();
}
}
int my_isStandalone(void * data)
{
int retval = 0;
PSAX_plain_callback(CB_ISSTANDALONE, data);
retval = Pike_sp[0-1].u.integer;
pop_stack();
return retval;
}
void my_startDocument(void * data)
{
PSAX_plain_callback(CB_STARTDOCUMENT, data);
}
void my_endDocument(void * data)
{
PSAX_plain_callback(CB_ENDDOCUMENT, data);
}
int my_hasInternalSubset(void * data)
{
return PSAX_plain_int_callback(CB_STARTDOCUMENT, data);
}
int my_hasExternalSubset(void * data)
{
return PSAX_plain_int_callback(CB_STARTDOCUMENT, data);
}
/*! @decl void set_callback(int callback_id, function f, mixed ... extra_args)
*!
*! sets a SAX handler callback function.
*!
*! @param callback_id
*! the id of the type of handler you wish to set. this should be
*! one of the @[Public.Parser.XML2.Constants].SAX_CB_* members.
*!
*! @param f
*! the function to call when the selected parsing event occurs.
*! prototypes for each event function are found in
*! @[Public.Parser.XML2.SAXHandlers].
*!
*! @param extra_args
*! extra data to supply to the callback function. these will be passed
*! as extra parameters after any provided by the parser.
*!
*!
*! void serror_cb(mapping(string:mixed) error, mixed ... extra_args);
*! mapping elements: domain, code, message, level, line, column
*!
*! void entitydecl_cb(string name, int type, string publicId, string systemId, string content, mixed ... extra_args);
*!
*! void elementdecl_cb(string name, int type, mixed ... extra_args);
*!
*! void unparsedentitydecl_cb(string name, string publicId, string systemId, string notationName, mixed ... extra_args);
*!
*! void attributedecl_cb(string elem, string fullname, int type, int def, string defaultValue, mixed ... extra_args);
*!
*! void notationdecl_cb(string name, string publicId, string systemId, mixed ... extra_args);
*!
*! void internalsubset_cb(string name, string ExternalId, string SystemId, mixed ... extra_args);
*!
*! void externalsubset_cb(string name, string ExternalId, string SystemId, mixed ... extra_args);
*!
*! void processinginstruction_cb(string target, string data, mixed ... extra_args);
*!
*! void endelement_cb(string name, mixed ... extra_args);
*!
*! void cdatablock_cb(string chars, mixed ... extra_args);
*!
*! void ignorablewhitespace(string chars, mixed ... extra_args);
*!
*! void characters_cb(string chars, mixed ... extra_args);
*!
*! void reference_cb(string name, mixed ... extra_args);
*!
*! void comment_cb(string value, mixed ... extra_args);
*!
*! void startelement_cb(string name, mapping(string:string) attributes, mixed ... extra_args);
*!
*! int isstandalone_cb(mixed ... extra_args);
*!
*! void startdocument_cb(mixed ... extra_args);
*!
*! void enddocument_cb(mixed ... extra_args);
*!
*! int hasinternalsubset(mixed ... extra_args);
*!
*! int hasexternalsubset(mixed ... extra_args);
*!
*! string resolveentity(string publicId, string systemId, mixed ... extra_args);
*!
*/
PIKEFUN void set_callback(int callback_id, function f, mixed ... extra_args)
{
struct svalue * ae;
//printf("setting callback %d\n", callback_id);
switch(callback_id)
{
case CB_GETENTITY:
mySAX->getEntity = my_getEntity;
break;
case CB_INTERNALSUBSET:
mySAX->internalSubset = my_internalSubset;
break;
case CB_ISSTANDALONE:
mySAX->isStandalone = my_isStandalone;
break;
case CB_HASINTERNALSUBSET:
mySAX->hasInternalSubset = my_hasInternalSubset;
break;
case CB_HASEXTERNALSUBSET:
mySAX->hasExternalSubset = my_hasExternalSubset;
break;
case CB_RESOLVEENTITY:
mySAX->resolveEntity = my_resolveEntity;
break;
case CB_ENTITYDECL:
mySAX->entityDecl = my_entityDecl;
break;
case CB_NOTATIONDECL:
mySAX->notationDecl = my_notationDecl;
break;
case CB_ATTRIBUTEDECL:
mySAX->attributeDecl = my_attributeDecl;
break;
case CB_ELEMENTDECL:
mySAX->elementDecl = my_elementDecl;
break;
case CB_UNPARSEDENTITYDECL:
mySAX->unparsedEntityDecl = my_unparsedEntityDecl;
break;
case CB_STARTDOCUMENT:
mySAX->startDocument = my_startDocument;
break;
case CB_ENDDOCUMENT:
mySAX->endDocument = my_endDocument;
break;
case CB_STARTELEMENT:
mySAX->startElement = my_startElement;
break;
case CB_ENDELEMENT:
mySAX->endElement = my_endElement;
break;
case CB_REFERENCE:
mySAX->reference = my_reference;
break;
case CB_CHARACTERS:
mySAX->characters = my_characters;
break;
case CB_IGNORABLEWHITESPACE:
mySAX->ignorableWhitespace = my_ignorableWhitespace;
break;
case CB_PROCESSINGINSTRUCTION:
mySAX->processingInstruction = my_processingInstruction;
break;
case CB_COMMENT:
mySAX->comment = my_comment;
break;
case CB_GETPARAMETERENTITY:
mySAX->getParameterEntity = my_getParameterEntity;
break;
case CB_CDATABLOCK:
mySAX->cdataBlock = my_cdataBlock;
break;
case CB_EXTERNALSUBSET:
mySAX->externalSubset = my_externalSubset;
break;
case CB_STARTELEMENTNS:
mySAX->startElementNs = my_startElementNs;
break;
case CB_ENDELEMENTNS:
mySAX->endElementNs = my_endElementNs;
break;
case CB_SERROR:
mySAX->serror = my_serror;
break;
default:
Pike_error("unknown callback identifier.\n");
}
f_aggregate(args-2);
make_PSAX_handler();
if(ITEM(THIS->object_data->handlers)[callback_id].type!=PIKE_T_INT)
{
ae = &(ITEM(THIS->object_data->handlers)[callback_id]);
free_svalue(ae);
push_int(0);
ITEM(THIS->object_data->handlers)[callback_id] = Pike_sp[0-1];
ae = &(ITEM(THIS->object_data->handlers)[callback_id]);
pop_stack();
}
// add_ref(f->u.efun);
(ITEM(THIS->object_data->handlers)[callback_id]) = Pike_sp[0-1];
pop_n_elems(args);
}
/*! @decl int clear_callback(int callback_id)
*!
*! clears a SAX handler callback.
*!
*! @param callback_id
*! the id of the type of handler you wish to set. this should be
*! one of the @[Public.Parser.XML2.Constants].SAX_CB_* members.
*!
*! @returns
*! 1 if the handler existed, 0 otherwise.
*/
PIKEFUN void clear_callback(int callback_id)
{
struct svalue * ae;
switch(callback_id)
{
case CB_GETENTITY:
mySAX->getEntity = NULL;
break;
case CB_INTERNALSUBSET:
mySAX->internalSubset = NULL;
break;
case CB_ISSTANDALONE:
mySAX->isStandalone = NULL;
break;
case CB_HASINTERNALSUBSET:
mySAX->hasInternalSubset = NULL;
break;
case CB_HASEXTERNALSUBSET:
mySAX->hasExternalSubset = NULL;
break;
case CB_RESOLVEENTITY:
mySAX->resolveEntity = NULL; /* TODO: needs more thought. */
break;
case CB_ENTITYDECL:
mySAX->entityDecl = NULL;
break;
case CB_NOTATIONDECL:
mySAX->notationDecl = NULL;
break;
case CB_ATTRIBUTEDECL:
mySAX->attributeDecl = NULL;
break;
case CB_ELEMENTDECL:
mySAX->elementDecl = NULL;
break;
case CB_UNPARSEDENTITYDECL:
mySAX->unparsedEntityDecl = NULL;
break;
case CB_STARTDOCUMENT:
mySAX->startDocument = NULL;
break;
case CB_ENDDOCUMENT:
mySAX->endDocument = NULL;
break;
case CB_STARTELEMENT:
mySAX->startElement = NULL;
break;
case CB_ENDELEMENT:
mySAX->endElement = NULL;
break;
case CB_REFERENCE:
mySAX->reference = NULL;
break;
case CB_CHARACTERS:
mySAX->characters = NULL;
break;
case CB_IGNORABLEWHITESPACE:
mySAX->ignorableWhitespace = NULL;
break;
case CB_PROCESSINGINSTRUCTION:
mySAX->processingInstruction = NULL;
break;
case CB_COMMENT:
mySAX->comment = NULL;
break;
case CB_GETPARAMETERENTITY:
mySAX->getParameterEntity = NULL; /* TODO: needs more thought. */
break;
case CB_CDATABLOCK:
mySAX->cdataBlock = NULL;
break;
case CB_EXTERNALSUBSET:
mySAX->externalSubset = NULL;
break;
case CB_STARTELEMENTNS:
mySAX->startElementNs = NULL;
break;
case CB_ENDELEMENTNS:
mySAX->endElementNs = NULL;
break;
case CB_SERROR:
mySAX->serror = NULL;
break;
default:
Pike_error("unknown callback identifier.\n");
}
if(ITEM(THIS->object_data->handlers)[callback_id].type!=PIKE_T_INT)
{
ae = &(ITEM(THIS->object_data->handlers)[callback_id]);
free_svalue(ae);
push_int(0);
ITEM(THIS->object_data->handlers)[callback_id] = Pike_sp[0-1];
ae = &(ITEM(THIS->object_data->handlers)[callback_id]);
}
pop_stack();
}
PIKEFUN void create()
{
}
/*! @decl int feed(string d, string|void encoding)
*!
*! feed some XML data to the parser. @[feed] may be called multiple
*! times to pass an entire XML document to the parser. The document
*! will be processed as data is fed to the parser.
*!
*! @param d
*! some XML data to be parsed. need not be a complete XML document.
*!
*! @returns
*! the number of bytes processed.
*/
PIKEFUN int feed(string d, string encoding)
{
int retval;
xmlParserCtxtPtr context;
xmlCharEncodingHandlerPtr enc;
if(THIS->object_data->context == NULL)
{
context = xmlCreatePushParserCtxt(mySAX, NULL, NULL, 0, NULL);
if(context == NULL) Pike_error("unable to create parser context.\n");
THIS->object_data->context = context;
}
/* FIXME: will this cause a memory leak? */
enc = xmlFindCharEncodingHandler(encoding->str);
if(enc != NULL)
{
xmlSwitchToEncoding(context, enc);
context->charset = XML_CHAR_ENCODING_UTF8;
}
retval = xmlParseChunk(THIS->object_data->context, d->str, d->len, 0);
pop_n_elems(args);
push_int(retval);
}
PIKEFUN int feed(string d)
{
int retval;
xmlParserCtxtPtr context;
if(THIS->object_data->context == NULL)
{
context = xmlCreatePushParserCtxt(mySAX, NULL, NULL, 0, NULL);
if(context == NULL) Pike_error("unable to create parser context.\n");
THIS->object_data->context = context;
}
retval = xmlParseChunk(THIS->object_data->context, d->str, d->len, 0);
pop_n_elems(args);
push_int(retval);
}
/*! @decl int end()
*!
*! end parsing of a document and prepare for the next document.
*!
*! resets the document parsing context and prepares for the next
*! document. @[end] should be called after the last chunk of data
*! in an XML document has been passed to @[feed].
*/
PIKEFUN int end()
{
int retval;
xmlParserCtxtPtr context;
char * b = "foo";
if(THIS->object_data->context == NULL)
{
context = xmlCreatePushParserCtxt(mySAX, NULL, NULL, 0, NULL);
if(context == NULL) Pike_error("unable to create parser context.\n");
THIS->object_data->context = context;
}
retval = xmlParseChunk(THIS->object_data->context, b, 0, 1);
push_int(retval);
if(THIS->object_data->context != NULL)
{
xmlFreeParserCtxt(THIS->object_data->context);
THIS->object_data->context = NULL;
}
}
/*! @decl int parse(string d, string|void encoding)
*!
*! feed a complete XML document to the parser. data from the document
*! will be processed and any registered SAX handler callbacks will
*! be called as SAX events occur. this method contains an implicit
*! call to @[end], so that the context is prepared to receive a new
*! document after this function returns.
*!
*! you may call this method with an (ending) fragment of an XML
*! document, as long as any previous data needed to produce a valid
*! XML document has already been fed to the parser using @[feed].
*!
*! @param d
*! some XML data to be parsed. need not be a complete XML document.
*!
*! @returns
*! the number of bytes processed.
*/
PIKEFUN int parse(string d)
{
int retval;
xmlParserCtxtPtr context;
xmlSAXHandlerPtr ySAX;
printf("running...\n");
if(THIS->object_data->context == NULL)
{
context = xmlCreatePushParserCtxt(mySAX, NULL, NULL, 0, NULL);
if(context == NULL) Pike_error("unable to create parser context.\n");
THIS->object_data->context = context;
}
retval = xmlParseChunk(THIS->object_data->context, d->str, d->len, 0);
retval = xmlParseChunk(THIS->object_data->context, d->str, 0, 1);
if(THIS->object_data->context != NULL)
{
xmlFreeParserCtxt(THIS->object_data->context);
THIS->object_data->context=NULL;
}
pop_n_elems(args);
/*
{
const struct svalue *s;
int i = 0;
for(i=0; i < 10; i++)
{
printf("val %d\n", i);
{
char *s;
dynamic_buffer save_buf;
init_buf(&save_buf);
describe_svalue(Pike_sp-i,0,0);
s=simple_free_buf(&save_buf);
fprintf(stderr,"- value: %s\n",s);
free(s);
}
}
}
*/
push_int(retval);
}
PIKEFUN int parse(string d, string encoding)
{
int retval;
xmlParserCtxtPtr context;
xmlSAXHandlerPtr ySAX;
xmlCharEncodingHandlerPtr enc;
if(THIS->object_data->context == NULL)
{
context = xmlCreatePushParserCtxt(mySAX, NULL, NULL, 0, NULL);
if(context == NULL) Pike_error("unable to create parser context.\n");
THIS->object_data->context = context;
}
/* FIXME: will this cause a memory leak? */
enc = xmlFindCharEncodingHandler(encoding->str);
if(enc != NULL)
{
xmlSwitchToEncoding(context, enc);
context->charset = XML_CHAR_ENCODING_UTF8;
}
f_SAX_parse(1);
}
INIT
{
SAX_OBJECT_DATA * sax;
struct array * handlers;
xmlParserCtxtPtr context;
sax = malloc(sizeof(SAX_OBJECT_DATA));
if(sax == NULL)
Pike_error("sax_init: out of memory.\n");
sax->sax = malloc(sizeof(struct _xmlSAXHandler));
push_int(30);
f_allocate(1);
handlers = Pike_sp[0-1].u.array;
add_ref(handlers);
sax->handlers = handlers;
pop_stack();
THIS->object_data = sax;
THIS->object_data->context = NULL;
// for SAX2
mySAX->initialized = XML_SAX2_MAGIC;
mySAX->internalSubset = NULL;
mySAX->isStandalone = NULL;
mySAX->hasInternalSubset = NULL;
mySAX->hasExternalSubset = NULL;
mySAX->resolveEntity = NULL;
mySAX->entityDecl = NULL;
mySAX->notationDecl = NULL;
mySAX->attributeDecl = NULL;
mySAX->elementDecl = NULL;
mySAX->unparsedEntityDecl = NULL;
mySAX->startDocument = NULL;
mySAX->endDocument = NULL;
mySAX->startElement = NULL;
mySAX->endElement = NULL;
mySAX->reference = NULL;
mySAX->characters = NULL;
mySAX->ignorableWhitespace = NULL;
mySAX->processingInstruction = NULL;
mySAX->comment = NULL;
mySAX->setDocumentLocator = NULL;
mySAX->getParameterEntity = NULL;
mySAX->getEntity = NULL;
mySAX->cdataBlock = NULL;
mySAX->externalSubset = NULL;
mySAX->startElementNs = NULL;
mySAX->endElementNs = NULL;
mySAX->serror = NULL;
xmlDefaultSAXHandlerInit();
}
EXIT
{
if(THIS->object_data->context != NULL)
{
xmlFreeParserCtxt(THIS->object_data->context);
}
if(THIS->object_data->sax != NULL)
{
free(THIS->object_data->sax);
}
if(THIS->object_data->handlers != NULL)
{
int x = 0;
for(x = 0; x < THIS->object_data->handlers->size; x++)
{
free_svalue(&ITEM(THIS->object_data->handlers)[x]);
}
free_array(THIS->object_data->handlers);
}
if(THIS->object_data)
free(THIS->object_data);
}
PIKECLASS PSAXHandler
{
PIKEVAR array user_data;
PIKEVAR function cb;
PIKEFUN void create(function cb, array user_data)
{
THIS->user_data = user_data;
add_ref(user_data);
assign_svalue(&(THIS->cb), cb);
add_ref(THIS->cb.u.efun);
add_ref(THIS->user_data);
}
EXIT
{
// printf("PSAXHandler exit\n");
free_array(THIS->user_data);
free_svalue(& THIS->cb);
}
}
}
void make_PSAX_handler()
{
struct object * o;
o = clone_object(SAX_PSAXHandler_program, 2);
push_object(o);
add_ref(o);
return;
}
struct array * get_callback_data(struct object * o)
{
return OBJ2_SAX_PSAXHANDLER(o)->user_data;
}
struct svalue * get_callback_func(struct object * o)
{
return &(OBJ2_SAX_PSAXHANDLER(o)->cb);
}
/*! @endclass
*!
*/
/*! @endmodule
*!
*/
/*! @endmodule
*!
*/
/*! @endmodule
*!
*/
void pike_init_xml2_sax(void)
{
INIT
}
void pike_exit_xml2_sax(void)
{
EXIT
}