gambas-source-code/gb.libxml/src/CXMLReader.c
Benoît Minisini de083e583d [GB.LIBXML]
* NEW: Rename the gb.xml component as gb.libxml.

[GB.LIBXML.XSLT]
* NEW: Rename the gb.xml.xslt component as gb.libxml.xslt

[GB.LIBXML.RPC]
* NEW: Rename the gb.xml.rpc component as gb.libxml.rpc


git-svn-id: svn://localhost/gambas/trunk@4640 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2012-04-20 01:01:48 +00:00

517 lines
11 KiB
C

/***************************************************************************
CXMLReader.c
(c) 2004 Daniel Campos Fernández <danielcampos@netcourrier.com>
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, 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., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#define __CXMLREADER_C
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <libxml/xmlreader.h>
#include "main.h"
#include "CXMLReader.h"
unsigned char b64value(char car)
{
if ( (car>=65) && (car<=90) ) return car-65;
if ( (car>=97) && (car<=122) ) return car-71;
if ( (car>=48) && (car<=57) ) return car+4;
if (car=='+') return 62;
if (car=='/') return 63;
if (car=='=') return 254;
return 255;
}
void FromBinHex(char *src,char *dst)
{
char b;
unsigned long bucle;
int zone=0;
for (bucle=0;bucle<strlen(src);bucle++)
{
switch (toupper(src[bucle]))
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
b=src[bucle]-48; break;
default:
b=src[bucle]-55;
}
switch(zone)
{
case 0:
dst[bucle/2]=b<<4;
zone=1;
break;
default:
dst[bucle/2]+=b;
zone=0;
break;
}
}
}
unsigned long FromBase64(char *src,char *dst)
{
unsigned long bucle,retval=0;
unsigned char car;
int zone=0;
int pads=0;
for (bucle=0;bucle<strlen(src);bucle++)
{
car=b64value(src[bucle]);
switch (car)
{
case 255: break;
case 254:
zone=4;
pads++;
if (pads==3) return retval-pads;
break;
default:
switch(zone)
{
case 0:
retval+=3;
dst[retval-3]=car<<2;
zone++;
break;
case 1:
dst[retval-3]+=(car>>4);
dst[retval-2]=car<<4;
zone++;
break;
case 2:
dst[retval-2]+=car>>2;
dst[retval-1]=car<<6;
zone++;
break;
case 3:
dst[retval-1]+=car;
zone=0;
break;
case 4:
return retval;
}
}
}
return retval-pads;
}
int Check_Reader(CXMLREADER *test)
{
if (!test->reader)
{
GB.Error("No XML file or string to read from");
return 1;
}
if (test->eof)
{
GB.Error("Reached end of file");
return 1;
}
return 0;
}
void Free_Reader(CXMLREADER *test)
{
if (test->buffer)GB.Free(POINTER(&test->buffer));
if (test->reader)
{
xmlTextReaderClose(test->reader);
xmlFreeTextReader(test->reader);
test->reader=NULL;
}
test->eof=0;
}
BEGIN_METHOD (CXmlReader_Open,GB_STRING FileName)
Free_Reader(THIS);
THIS->reader=xmlReaderForFile(GB.ToZeroString(ARG(FileName)),NULL,0);
if (!THIS->reader) GB.Error ("Unable to parse XML file");
END_METHOD
BEGIN_METHOD (CXmlReader_FromString,GB_STRING Buffer;GB_STRING URL;)
if (!LENGTH(Buffer))
{
GB.Error ("Unable to parse NULL string");
return;
}
Free_Reader(THIS);
GB.Alloc(POINTER(&THIS->buffer),LENGTH(Buffer));
memcpy (THIS->buffer,STRING(Buffer),LENGTH(Buffer));
if (!MISSING(URL))
THIS->reader=xmlReaderForMemory(THIS->buffer,LENGTH(Buffer),GB.ToZeroString(ARG(URL)),NULL,0);
else
THIS->reader=xmlReaderForMemory(THIS->buffer,LENGTH(Buffer),"",NULL,0);
if (!THIS->reader) GB.Error ("Unable to parse XML file");
END_METHOD
BEGIN_METHOD_VOID (CXmlReader_Read)
int retval;
if (Check_Reader(THIS)) return;
retval=xmlTextReaderRead(THIS->reader);
switch(retval)
{
case 0:
THIS->eof=1;
break;
case -1:
Free_Reader(THIS);
GB.Error("Error parsing XML file");
break;
}
END_METHOD
BEGIN_METHOD (CXmlReader_Decode,GB_STRING Data;GB_STRING Encoding;)
char *dst=NULL;
unsigned long len;
if (!strcasecmp(GB.ToZeroString(ARG(Encoding)),"base64") ) {
if (!LENGTH(Data)) return;
GB.Alloc (POINTER(&dst),LENGTH(Data) );
len=FromBase64(GB.ToZeroString(ARG(Data)),dst);
GB.ReturnNewString(dst,len);
GB.Free(POINTER(&dst));
return;
}
if (!strcasecmp(GB.ToZeroString(ARG(Encoding)),"binhex") ) {
if (!LENGTH(Data)) return;
if (LENGTH(Data)%2) return;
dst=STRING(Data);
for(len=0;len<LENGTH(Data);len++)
{
switch (toupper(dst[len]))
{
case '0': case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9': case 'A': case 'B':
case 'C': case 'D': case 'E': case 'F': break;
default: return;
}
}
dst=NULL;
GB.Alloc (POINTER(&dst),LENGTH(Data)/2);
FromBinHex(GB.ToZeroString(ARG(Data)),dst);
GB.ReturnNewString(dst,LENGTH(Data)/2);
GB.Free(POINTER(&dst));
return;
}
GB.Error ("Invalid encoding");
END_METHOD
BEGIN_PROPERTY (CXMLReader_Node)
RETURN_SELF();
END_PROPERTY
BEGIN_METHOD_VOID(CXmlReader_Free)
Free_Reader(THIS);
END_METHOD
BEGIN_METHOD_VOID(CXmlReader_next)
char *wenum=(char*)GB.GetEnum();
int eval;
if (Check_Reader(THIS))
{
GB.StopEnum();
return;
}
if (!wenum[0]) eval=xmlTextReaderMoveToFirstAttribute(THIS->reader);
else eval=xmlTextReaderMoveToNextAttribute(THIS->reader);
if (eval==-1)
{
xmlFreeTextReader(THIS->reader);
THIS->reader=NULL;
GB.StopEnum();
GB.Error("Error parsing XML file");
return;
}
if (!eval)
{
if (wenum[0]) xmlTextReaderMoveToElement(THIS->reader);
GB.StopEnum();
return;
}
wenum[0]=1;
RETURN_SELF();
END_METHOD
BEGIN_PROPERTY(CXmlReader_count)
int nval;
if (Check_Reader(THIS)) return;
nval=xmlTextReaderAttributeCount(THIS->reader);
if (nval==-1)
{
xmlFreeTextReader(THIS->reader);
THIS->reader=NULL;
GB.Error("Error parsing XML file");
return;
}
GB.ReturnInteger(nval);
END_METHOD
BEGIN_PROPERTY(CXMLReader_EOF)
if (!THIS->reader)
{
GB.ReturnBoolean(1);
return;
}
GB.ReturnBoolean(THIS->eof);
END_PROPERTY
BEGIN_PROPERTY(CRNODE_BaseUri)
if (Check_Reader(THIS)) return;
GB.ReturnNewZeroString((const char *)xmlTextReaderBaseUri(THIS->reader));
END_PROPERTY
BEGIN_PROPERTY(CRNODE_Depth)
if (Check_Reader(THIS)) return;
GB.ReturnInteger( xmlTextReaderDepth(THIS->reader));
END_PROPERTY
BEGIN_PROPERTY(CRNODE_IsDefault)
if (Check_Reader(THIS)) return;
GB.ReturnBoolean(xmlTextReaderIsDefault(THIS->reader));
END_PROPERTY
BEGIN_PROPERTY(CRNODE_IsEmptyElement)
if (Check_Reader(THIS)) return;
GB.ReturnBoolean(xmlTextReaderIsEmptyElement(THIS->reader));
END_PROPERTY
BEGIN_PROPERTY(CRNODE_LocalName)
if (Check_Reader(THIS)) return;
GB.ReturnNewZeroString((const char *)xmlTextReaderLocalName(THIS->reader));
END_PROPERTY
BEGIN_PROPERTY(CRNODE_Name)
if (Check_Reader(THIS)) return;
GB.ReturnNewZeroString((const char *)xmlTextReaderName(THIS->reader));
END_PROPERTY
BEGIN_PROPERTY(CRNODE_NamespaceUri)
if (Check_Reader(THIS)) return;
GB.ReturnNewZeroString((const char *)xmlTextReaderNamespaceUri(THIS->reader));
END_PROPERTY
BEGIN_PROPERTY(CRNODE_Prefix)
if (Check_Reader(THIS)) return;
GB.ReturnNewZeroString((const char *)xmlTextReaderPrefix(THIS->reader));
END_PROPERTY
BEGIN_PROPERTY(CRNODE_QuoteChar)
char car='\"';
if (Check_Reader(THIS)) return;
car=(char)xmlTextReaderQuoteChar(THIS->reader);
GB.ReturnNewString(&car,1);
END_PROPERTY
BEGIN_PROPERTY(CRNODE_Value)
char *buf;
if (Check_Reader(THIS)) return;
buf=(char *)xmlTextReaderValue(THIS->reader);
GB.ReturnNewZeroString(buf);
if (buf) xmlFree(buf);
END_PROPERTY
BEGIN_PROPERTY(CRNODE_Type)
if (Check_Reader(THIS)) return;
GB.ReturnInteger( xmlTextReaderNodeType(THIS->reader));
END_PROPERTY
BEGIN_PROPERTY(CRNODE_XmlLang)
if (Check_Reader(THIS)) return;
GB.ReturnNewZeroString((char *)xmlTextReaderXmlLang(THIS->reader));
END_PROPERTY
GB_DESC CXmlReaderNodeTypeDesc[] =
{
GB_DECLARE("XmlReaderNodeType", 0), GB_VIRTUAL_CLASS(),
GB_CONSTANT("None", "i", XML_READER_TYPE_NONE),
GB_CONSTANT("Element", "i", XML_READER_TYPE_ELEMENT),
GB_CONSTANT("Attribute", "i", XML_READER_TYPE_ATTRIBUTE),
GB_CONSTANT("Text", "i",XML_READER_TYPE_TEXT),
GB_CONSTANT("CDATA", "i", XML_READER_TYPE_CDATA),
GB_CONSTANT("EntityReference", "i", XML_READER_TYPE_ENTITY_REFERENCE),
GB_CONSTANT("Entity", "i",XML_READER_TYPE_ENTITY),
GB_CONSTANT("ProcessingInstruction", "i",XML_READER_TYPE_PROCESSING_INSTRUCTION),
GB_CONSTANT("Comment", "i", XML_READER_TYPE_COMMENT),
GB_CONSTANT("Document", "i", XML_READER_TYPE_DOCUMENT),
GB_CONSTANT("DocumentType", "i", XML_READER_TYPE_DOCUMENT_TYPE),
GB_CONSTANT("DocumentFragment", "i", XML_READER_TYPE_DOCUMENT_FRAGMENT),
GB_CONSTANT("Notation", "i", XML_READER_TYPE_NOTATION),
GB_CONSTANT("Whitespace", "i",XML_READER_TYPE_WHITESPACE),
GB_CONSTANT("SignificantWhitespace", "i",XML_READER_TYPE_SIGNIFICANT_WHITESPACE),
GB_CONSTANT("EndElement", "i", XML_READER_TYPE_END_ELEMENT),
GB_CONSTANT("EndEntity", "i", XML_READER_TYPE_END_ENTITY),
GB_CONSTANT("XmlDeclaration", "i",XML_READER_TYPE_XML_DECLARATION),
GB_END_DECLARE
};
GB_DESC CXmlReaderNodeAttributesDesc[] =
{
GB_DECLARE(".XmlReader.Node.Attributes", 0), GB_VIRTUAL_CLASS(),
GB_METHOD("_next", ".XmlReader.Node", CXmlReader_next, NULL),
GB_PROPERTY_READ("Count", "i", CXmlReader_count),
GB_END_DECLARE
};
GB_DESC CXmlReaderNodeDesc[] =
{
GB_DECLARE(".XmlReader.Node", 0), GB_VIRTUAL_CLASS(),
GB_PROPERTY_READ("Attributes", ".XmlReader.Node.Attributes",CXMLReader_Node),
GB_PROPERTY_READ("BaseUri","s",CRNODE_BaseUri),
GB_PROPERTY_READ("Depth","i",CRNODE_Depth),
GB_PROPERTY_READ("IsDefault","b",CRNODE_IsDefault),
GB_PROPERTY_READ("IsEmptyElement","b",CRNODE_IsEmptyElement),
GB_PROPERTY_READ("LocalName","s",CRNODE_LocalName),
GB_PROPERTY_READ("Name", "s", CRNODE_Name),
GB_PROPERTY_READ("NamespaceUri", "s", CRNODE_NamespaceUri),
GB_PROPERTY_READ("Prefix", "s", CRNODE_Prefix),
GB_PROPERTY_READ("QuoteChar", "s", CRNODE_QuoteChar),
GB_PROPERTY_READ("Type","i",CRNODE_Type),
GB_PROPERTY_READ("Value", "s", CRNODE_Value),
GB_PROPERTY_READ("XmlLang", "s", CRNODE_XmlLang),
GB_END_DECLARE
};
GB_DESC CXmlReaderDesc[] =
{
GB_DECLARE("XmlReader", sizeof(CXMLREADER)),
GB_STATIC_METHOD("Decode","s",CXmlReader_Decode,"(Data)s(Encoding)s"),
GB_METHOD("_free",NULL,CXmlReader_Free,NULL),
GB_METHOD("Open", NULL, CXmlReader_Open,"(FileName)s"),
GB_METHOD("Close",NULL,CXmlReader_Free,NULL),
GB_METHOD("FromString",NULL,CXmlReader_FromString,"(Buffer)s[(URL)s]"),
GB_METHOD("Read",NULL,CXmlReader_Read,NULL),
GB_PROPERTY_READ("Eof","b",CXMLReader_EOF),
GB_PROPERTY_READ("Node",".XmlReader.Node",CXMLReader_Node),
GB_END_DECLARE
};