Logo Search packages:      
Sourcecode: gambas version File versions  Download package

CXMLReader.c

/***************************************************************************

  CXMLReader.c

  libxml wrapper

  (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 1, 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.

***************************************************************************/



#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((void**)&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((void**)&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 ((void**)&dst,LENGTH(Data) );
            len=FromBase64(GB.ToZeroString(ARG(Data)),dst);
            GB.ReturnNewString(dst,len);
            GB.Free((void**)&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 ((void**)&dst,LENGTH(Data)/2);
            FromBinHex(GB.ToZeroString(ARG(Data)),dst);
            GB.ReturnNewString(dst,LENGTH(Data)/2);
            GB.Free((void**)&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.ReturnNewString(xmlTextReaderBaseUri(THIS->reader),0);

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.ReturnNewString(xmlTextReaderLocalName(THIS->reader),0);

END_PROPERTY

BEGIN_PROPERTY(CRNODE_Name)

      if (Check_Reader(THIS)) return;
      GB.ReturnNewString(xmlTextReaderName(THIS->reader),0);

END_PROPERTY

BEGIN_PROPERTY(CRNODE_NamespaceUri)

      if (Check_Reader(THIS)) return;
      GB.ReturnNewString(xmlTextReaderNamespaceUri(THIS->reader),0);

END_PROPERTY

BEGIN_PROPERTY(CRNODE_Prefix)

      if (Check_Reader(THIS)) return;
      GB.ReturnNewString(xmlTextReaderPrefix(THIS->reader),0);

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=xmlTextReaderValue(THIS->reader);
      GB.ReturnNewString(buf,0);
      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.ReturnNewString(xmlTextReaderXmlLang(THIS->reader),0);

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_DESC CXmlReaderNodeDesc[] =
{

      GB_DECLARE(".XmlReaderNode", 0), GB_VIRTUAL_CLASS(),
  
      GB_PROPERTY_READ("Attributes", ".XmlReaderNodeAttributes",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 CXmlReaderNodeAttributesDesc[] =
{
      GB_DECLARE(".XmlReaderNodeAttributes", 0), GB_VIRTUAL_CLASS(),
      
      GB_METHOD("_next", ".XmlReaderNode", CXmlReader_next, NULL),
        GB_PROPERTY_READ("Count", "i", CXmlReader_count),

      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",".XmlReaderNode",CXMLReader_Node),
  
  GB_END_DECLARE
};





Generated by  Doxygen 1.6.0   Back to index