[Gambas-devel] Component using Collection object

Christian Faure christian.faurebouvard at ...156...
Sat Sep 4 01:42:51 CEST 2004


Hi,
Ok, i have do corrections (thanks again), 
Now i can pass an empty collection as event argument. Ok

> I could create such an API, unless this is only for a test. Tell me what you 
> want to do exactly.

Not is a test, is a component for parsing XML files using expat library 
(C source at bottom).
The expat library need somes handlers (functions) for processing XML tags, 
then i want implement's as gambas-events, 
The problem:  StartElement handler:

  sub xml_StartElement(Name as String, Attributes as Collection)

I need populate this collection, 
then i apreciate very much :) an api like  (for the next version)
   GB.NewVariant(GB_T_CSTRING,  const char *str)
or any other way that you suggest.

As workaround, i have implemented two extra events:
  BeforeStartElement(name) fired once
  Attribute(name,value) fired for each attribute, bad way :(

In gbx_c_settings.c, at read_line function you do like this:
	...
	VALUE result;
	...
 	result.type = T_CSTRING;
 	result._string.addr = val;
	result._string.start = 0;
	result._string.len = val_len;
	VALUE_conv(&result, T_VARIANT);
 	GB_CollectionSet(THIS->table, key, key_len, (GB_VARIANT *)&result);
	...
this require somes extra includes, not usual for a independent component,
but if correct for my component, then i use them.

Thanks again...

Regards,
Christian



// begin expatc.c ------------------------------------------

#define __Expatc_C
#include "expatc.h"

#include <stdio.h>
#include <string.h>
#include <expat.h>


//#define DEBUG
DECLARE_EVENT(BeforeStartElement);
DECLARE_EVENT(Attribute);
DECLARE_EVENT(StartElement);
DECLARE_EVENT(EndElement);
DECLARE_EVENT(ParserError);
DECLARE_EVENT(CharacterData);
DECLARE_EVENT(Comment);
DECLARE_EVENT(ProcessingInstruction);
DECLARE_EVENT(StartCData);
DECLARE_EVENT(EndCData);
DECLARE_EVENT(Default);


static void XMLCALL
startElement(void *_object, const char *name, const char **atts)
{
    int i;  
    GB_COLLECTION col;
    //GB_VALUE v;
    #ifdef DEBUG
    printf("expatc::startElement [%s]\n",name);
    for( i=0;atts[i];i+=2){
        printf("\t%s=[%s]\n",atts[i],atts[i+1]);
    }
    #endif
    GB.Raise(THIS,BeforeStartElement,1,GB_T_STRING, name, strlen(name));
    GB.Collection.New ( &col , GB_COMP_TEXT );
    GB.Ref(col);
    for( i=0;atts[i];i+=2){
        GB.Raise(THIS,Attribute,2,
            GB_T_STRING, atts[i], strlen(atts[i]),
            GB_T_STRING, atts[i+1], strlen(atts[i+1]));
 
        //GB.Collection.Set ( col, atts[i], strlen(atts[i]) , (GB_VARIANT 
*)&v);
    }   
    GB.Raise(THIS,StartElement,2,GB_T_STRING, name, strlen(name),
                    GB_T_OBJECT,col);
    GB.Unref((void **)&col);
}

static void XMLCALL
endElement(void *_object, const char *name)
{
  #ifdef DEBUG
  printf("expatc::endElement [%s]\n",name);
  #endif
  GB.Raise(THIS,EndElement,1,GB_T_STRING, name, strlen(name));
}

static void XMLCALL
characterData(void *_object, const XML_Char *s, int len)
{
  char *copia;
  copia=strndup(s,len);
  #ifdef DEBUG
  printf("expatc::characterData %d [%s]\n",len,copia);
  #endif
  GB.Raise(THIS,CharacterData,1,GB_T_STRING, copia, len);
  free(copia);
}

static void XMLCALL
comment(void *_object, const XML_Char *s)
{
  #ifdef DEBUG
  printf("expatc::comment %d [%s]\n",strlen(s),s);
  #endif
  GB.Raise(THIS,Comment,1,GB_T_STRING, s, strlen(s));
}


static void XMLCALL
processingInstruction(void *_object, const XML_Char *target, const XML_Char 
*data)
{
  #ifdef DEBUG
  printf("expatc::processingInstruction %s [%s]\n",target,data);
  #endif
  GB.Raise(THIS,ProcessingInstruction,2,
      GB_T_STRING, target, strlen(target),
      GB_T_STRING, data, strlen(data));
}

static void XMLCALL
startCData(void *_object)
{
  #ifdef DEBUG
  printf("expatc::startCData\n");
  #endif
  GB.Raise(THIS,StartCData,0);
}

static void XMLCALL
endCData(void *_object)
{
  #ifdef DEBUG
  printf("expatc::endCData\n");
  #endif
  GB.Raise(THIS,EndCData,0);
}

static void XMLCALL
defaultHandler(void *_object, const XML_Char *s, int len)
{
  char *copia;
  copia=strndup(s,len);
  #ifdef DEBUG
  printf("expatc::defaultHandler %d [%s]\n",len,copia);
  #endif
  GB.Raise(THIS,Default,1,GB_T_STRING, copia, len);
  free(copia);
}

#define MSGSIZE 300
BEGIN_METHOD( CExpatc_Parse, GB_STRING Path; )
    char buf[BUFSIZ];
    char *path;
    char msg[MSGSIZE+1];
    XML_Parser parser;
    int done;
    FILE *in;
    path=GB.ToZeroString(ARG(Path));
    //strcpy(THIS->path,GB.ToZeroString(ARG(Path)));
    #ifdef DEBUG
    printf("expatc::Parse [%s]\n",path);
    #endif
    in=fopen(path,"rt");
    if(!in){
        snprintf(msg,MSGSIZE,"Can't open file [%s]",path);
	msg[MSGSIZE]=0;
        printf("expatc.c: Error: %s\n",msg);
        GB.Raise(THIS,ParserError,1,GB_T_STRING, msg, strlen(msg));
    }else{
        parser = XML_ParserCreate(NULL);
        XML_SetUserData(parser, THIS);
        XML_SetElementHandler(parser, startElement, endElement);
        XML_SetCharacterDataHandler(parser, characterData);
        XML_SetCommentHandler(parser, comment);
        XML_SetProcessingInstructionHandler(parser, processingInstruction);
        XML_SetStartCdataSectionHandler(parser, startCData);
        XML_SetEndCdataSectionHandler(parser, endCData);
        XML_SetDefaultHandler(parser, defaultHandler);
        do {
            size_t len = fread(buf, 1, sizeof(buf), in);
            done = len < sizeof(buf);
            if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
                snprintf(msg,MSGSIZE,
                        "%s at line %d\n",
                        XML_ErrorString(XML_GetErrorCode(parser)),
                        XML_GetCurrentLineNumber(parser));
		msg[MSGSIZE]=0;
                done=!0;//true
                printf("expatc.c: Error: %s\n",msg);
                GB.Raise(THIS,ParserError,1,GB_T_STRING, msg, strlen(msg));
            }
        } while (!done && !feof(in));
        XML_ParserFree(parser);
        fclose(in);
    }
END_METHOD


BEGIN_METHOD_VOID(CExpatc_new)
    #ifdef DEBUG
    printf("expatc::new\n");
    #endif
END_METHOD

BEGIN_METHOD_VOID(CExpatc_free)
    #ifdef DEBUG
    printf("expatc::free\n");
    #endif
END_METHOD


GB_DESC CExpatcDesc[] =
{
  GB_DECLARE("Expatc", sizeof(CExpatc)),
  GB_METHOD("Parse",NULL,CExpatc_Parse,"(Path)s"),
  GB_METHOD("_new",NULL,CExpatc_new,NULL),
  GB_METHOD("_free",NULL,CExpatc_free,NULL),
  GB_EVENT("BeforeStartElement", NULL, "(Name)s", &BeforeStartElement),
  GB_EVENT("Attribute", NULL, "(Name)s(Value)s", &Attribute),
  GB_EVENT("StartElement", NULL, "(Name)s(Attributes)o", &StartElement),
  GB_EVENT("EndElement", NULL, "(Name)s", &EndElement),
  GB_EVENT("ParserError", NULL, "(Msg)s", &ParserError),
  GB_EVENT("CharacterData", NULL, "(Txt)s", &CharacterData),
  GB_EVENT("Comment", NULL, "(Txt)s", &Comment),
  GB_EVENT("ProcessingInstruction", NULL, "(Target)s(Data)s", 
&ProcessingInstruction),
  GB_EVENT("StartCData", NULL, NULL, &StartCData),
  GB_EVENT("EndCData", NULL, NULL, &EndCData),        
  GB_EVENT("Default", NULL, "(Txt)s", &Default),        
  GB_END_DECLARE
};




More information about the Devel mailing list