[Gambas-devel] Component using Collection object

Benoit Minisini gambas at ...1...
Sat Sep 4 10:52:52 CEST 2004


On Saturday 04 September 2004 01:42, Christian Faure wrote:
> 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.

OK.

>
> 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.

When I develop components inside the interpreter, I can use the interpreter 
structures, constants and methods directly.

These structures and constants exist in gambas.h, they just have different 
names.

To put a string in the collection, you can do the same way, by just changing 
some constants and types. This should work :-)

GB_STRING result;

result.type = GB_T_CSTRING;
result._string.addr = attr_name;
result._string.start = 0;
result._string.len = strlen(attr_name);
GB.Conv((GB_VALUE *)&result, GB_T_VARIANT);
GB.Collection.Set(THIS->table, key, key_len, (GB_VARIANT *)&result);

>
> Thanks again...
>
> Regards,
> Christian
>
>

Just a few remarks :-)

1) What is the difference betweens expat and libxml2 ? Why using expat and not 
libxml2 ?

2) When you are finish the component, I will ask you to change your interface, 
i.e. the names you use, which are not very good.

For example, the name of the class is "Expatc", which is bad, as it is the 
name of the library. You must use something like "XMLParser", which is 
generic. This way, if there is another XML component based on a different 
library, they will be able to share the same interface so that the user don't 
have to change its code.

There are other problems, but finish your work without thinking about that. I 
will tell you later.

Regards,

>
> // 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
> };
>

-- 
Benoit Minisini
mailto:gambas at ...1...




More information about the Devel mailing list