[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