Home modules.gotpike.org
Username: Password: [Create Account]
[Forgot Password?]
Return to module

File Contents

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
}

 


gotpike.org | Copyright © 2004 - 2011 | Pike is a trademark of Department of Computer and Information Science, Linköping University