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

xml.cpp

/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2007, 2008, 2009 Teunis van Beelen
*
* teuniz@gmail.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 version 2 of the License.
*
* 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.
*
***************************************************************************
*
* This version of GPL is at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
*
***************************************************************************
*/


#include "xml.h"




int next_tag(int, struct xml_handle *);
int process_tag(const char *, struct xml_handle *);



struct xml_handle * xml_get_handle(const char *filename)
{
  struct xml_handle *handle_p;

  handle_p = (struct xml_handle *)s_calloc(1, sizeof(struct xml_handle));
  if(handle_p==NULL)  return(NULL);

  handle_p->level = 0;
  handle_p->offset = 0;
  handle_p->len = 0;
  handle_p->elementname = NULL;
  handle_p->attribute = NULL;
  handle_p->parent_handle_p = NULL;
  handle_p->child_handle_p = NULL;
  handle_p->tag_search_result = NULL;

  handle_p->file = fopen(filename, "rb");
  if(handle_p->file==NULL)
  {
    xml_close(handle_p);
    return(NULL);
  }

  handle_p->offset = next_tag(0, handle_p);
  if(handle_p->offset==-1)
  {
    xml_close(handle_p);
    return(NULL);
  }

  if(handle_p->tag_search_result==NULL)
  {
    xml_close(handle_p);
    return(NULL);
  }

  if(strcmp(handle_p->tag_search_result, "?xml version=\"1.0\"?"))
  {
    xml_close(handle_p);
    return(NULL);
  }

  handle_p->offset = next_tag(handle_p->offset, handle_p);
  if(handle_p->offset==-1)
  {
    xml_close(handle_p);
    return(NULL);
  }

  if(handle_p->tag_search_result==NULL)
  {
    xml_close(handle_p);
    return(NULL);
  }

  if(process_tag(handle_p->tag_search_result , handle_p))
  {
    xml_close(handle_p);
    return(NULL);
  }

  return(handle_p);
}





struct xml_handle * xml_create_handle(const char *filename, char *rootname)
{
  int len;

  struct xml_handle *handle_p;

  len = strlen(rootname);

  if(!len)  return(NULL);

  handle_p = (struct xml_handle *)s_calloc(1, sizeof(struct xml_handle));
  if(handle_p==NULL)  return(NULL);

  handle_p->level = 0;
  handle_p->offset = 0;
  handle_p->len = 0;
  handle_p->elementname = NULL;
  handle_p->attribute = NULL;
  handle_p->parent_handle_p = NULL;
  handle_p->child_handle_p = NULL;
  handle_p->tag_search_result = NULL;

  handle_p->file = fopen(filename, "wb+");
  if(handle_p->file==NULL)
  {
    s_free(handle_p);
    return(NULL);
  }

  fprintf(handle_p->file, "<?xml version=\"1.0\"?>\n<%s>\n</%s>\n", rootname, rootname);

  handle_p->offset = (ftell(handle_p->file) - len) - 4;

  handle_p->elementname = (char *)s_calloc(1, len + 1);
  if(handle_p->elementname==NULL)
  {
    fclose(handle_p->file);
    s_free(handle_p);
    return(NULL);
  }
  strncpy(handle_p->elementname, rootname, len);
  handle_p->elementname[len] = 0;

  return(handle_p);
}




char * xml_get_content_of_element(struct xml_handle *handle_p)
{
  int i, j, offset, len, deep=0;

  char *content;

  if(handle_p==NULL)  return(NULL);

  while(handle_p->child_handle_p!=NULL)
  {
    handle_p = handle_p->child_handle_p;
  }

  if(handle_p->elementname==NULL)  return(NULL);

  offset = handle_p->offset;

  len = strlen(handle_p->elementname);

  while(1)
  {
    offset = next_tag(offset, handle_p);
    if(offset == -1)
    {
      return(NULL);
    }

    if(handle_p->tag_search_result==NULL)
    {
      return(NULL);
    }

    if(handle_p->tag_search_result[0]=='/')
    {
      if(deep)  deep--;
      else  break;
    }
    else
    {
      deep++;
    }
  }

  offset -= (len + 3);

  if(offset<handle_p->offset)  return(NULL);

  fseek(handle_p->file, handle_p->offset, SEEK_SET);

  content = (char *)s_calloc(1, offset - handle_p->offset + 1);
  if(content==NULL)
  {
    return(NULL);
  }

  if(offset>handle_p->offset)
  {
    if(fread(content, offset - handle_p->offset, 1, handle_p->file) != 1)
    {
      s_free(content);
      return(NULL);
    }
  }

  content[offset - handle_p->offset] = 0;

  for(i=0; content[i]!=0; i++)
  {
    if(content[i]=='&')
    {
      if(!strncmp(content + i + 1, "lt", 2))
      {
        content[i] = '<';

        for(j=i+1; content[j-1]!=0; j++)
        {
          content[j] = content[j+2];
        }
      }

      if(!strncmp(content + i + 1, "amp", 3))
      {
        for(j=i+1; content[j-1]!=0; j++)
        {
          content[j] = content[j+3];
        }
      }
    }
  }

  return(content);
}




int xml_goto_next_element_with_same_name(struct xml_handle *handle_p)
{
  int len, offset, deep=0;

  if(handle_p==NULL)  return(1);

  while(handle_p->child_handle_p!=NULL)
  {
    handle_p = handle_p->child_handle_p;
  }

  if(handle_p->elementname==NULL)  return(1);

  len = strlen(handle_p->elementname);
  offset = handle_p->offset;

  while(1)
  {
    offset = next_tag(offset, handle_p);
    if(offset == -1)
    {
      return(1);
    }

    if(handle_p->tag_search_result==NULL)
    {
      return(1);
    }

    if(handle_p->tag_search_result[0]=='/')
    {
      if(deep)  deep--;
      else  break;
    }
    else
    {
      deep++;
    }
  }

  while(1)
  {
    offset = next_tag(offset, handle_p);
    if(offset == -1)
    {
      return(1);
    }

    if(handle_p->tag_search_result==NULL)
    {
      return(1);
    }

    if(handle_p->tag_search_result[0]=='/')
    {
      if(deep)  deep--;
      else  return(1);
    }
    else
    {
      if((int)strlen(handle_p->tag_search_result)>=len)
      {
        if((!strncmp(handle_p->tag_search_result, handle_p->elementname, len))&&(!deep))
        {
          if(process_tag(handle_p->tag_search_result, handle_p))
          {
            return(1);
          }

          handle_p->offset = offset;

          return(0);
        }
        else
        {
          deep++;
        }
      }
      else
      {
        deep++;
      }
    }
  }
}




int xml_goto_next_element_at_same_level(struct xml_handle *handle_p)
{
  int offset, deep=0;

  if(handle_p==NULL)  return(1);

  while(handle_p->child_handle_p!=NULL)
  {
    handle_p = handle_p->child_handle_p;
  }

  offset = handle_p->offset;

  while(1)
  {
    offset = next_tag(offset, handle_p);
    if(offset == -1)
    {
      return(1);
    }

    if(handle_p->tag_search_result==NULL)
    {
      return(1);
    }

    if(handle_p->tag_search_result[0]=='/')
    {
      if(deep)  deep--;
      else  break;
    }
    else
    {
      deep++;
    }
  }

  offset = next_tag(offset, handle_p);
  if(offset == -1)
  {
    return(1);
  }

  if(handle_p->tag_search_result==NULL)
  {
    return(1);
  }

  if(handle_p->tag_search_result[0]=='/')
  {
    return(1);
  }

  if(process_tag(handle_p->tag_search_result, handle_p))
  {
    return(1);
  }

  handle_p->offset = offset;

  return(0);
}




int xml_goto_nth_element_inside(struct xml_handle *handle_p, const char *name, int n)
{
  int len, offset, deep=0, cnt=0;

  struct xml_handle *new_handle_p;

  if(handle_p==NULL)  return(1);

  while(handle_p->child_handle_p!=NULL)
  {
    handle_p = handle_p->child_handle_p;
  }

  len = strlen(name);

  offset = handle_p->offset;

  while(1)
  {
    while(1)
    {
      offset = next_tag(offset, handle_p);
      if(offset == -1)
      {
        return(1);
      }

      if(handle_p->tag_search_result==NULL)
      {
        return(1);
      }

      if(handle_p->tag_search_result[0]=='/')
      {
        if(deep)  deep--;
        else  return(1);
      }
      else
      {
        deep++;
        break;
      }
    }

    if((int)strlen(handle_p->tag_search_result)>=len)
    {
      if(!strncmp(handle_p->tag_search_result, name, len))
      {
        if((handle_p->tag_search_result[len]==' ')||(handle_p->tag_search_result[len]==0))
        {
          if(cnt==n)
          {
            new_handle_p = (struct xml_handle *)s_calloc(1, sizeof(struct xml_handle));
            if(new_handle_p==NULL)
            {
              return(1);
            }

            handle_p->child_handle_p = new_handle_p;

            new_handle_p->file = handle_p->file;
            new_handle_p->level = handle_p->level + 1;
            new_handle_p->offset = offset;
            new_handle_p->len = 0;
            new_handle_p->elementname = NULL;
            new_handle_p->attribute = NULL;
            new_handle_p->parent_handle_p = handle_p;
            new_handle_p->child_handle_p = NULL;
            new_handle_p->tag_search_result = NULL;

            if(process_tag(handle_p->tag_search_result, new_handle_p))
            {
              return(1);
            }

            return(0);
          }

          cnt++;
        }
      }
    }
  }

  return(1);
}



int process_tag(const char * str, struct xml_handle * handle_p)
{
  int len, i;

  if(handle_p==NULL)  return(1);

  len = strlen(str);
  if(!len)  return(1);

  if((str[0]==' ')||(str[0]=='>'))  return(1);

  for(i=0; i<len; i++)
  {
    if((str[i]==' ')||(str[i]=='>'))  break;
  }

  if(handle_p->elementname)  s_free(handle_p->elementname);

  handle_p->elementname = (char *)s_calloc(1, i + 1);
  if(handle_p->elementname==NULL)  return(1);
  strncpy(handle_p->elementname, str, i);
  handle_p->elementname[i] = 0;

  return(0);
}



void xml_close(struct xml_handle *handle_p)  /* delete everything and close the file */
{
  if(handle_p!=NULL)
  {
    xml_goto_root(handle_p);

    if(handle_p->file!=NULL)  fclose(handle_p->file);
    if(handle_p->elementname)  s_free(handle_p->elementname);
    if(handle_p->attribute)  s_free(handle_p->attribute);
    if(handle_p->tag_search_result)  s_free(handle_p->tag_search_result);
    s_free(handle_p);
    handle_p = NULL;
  }
}



void xml_goto_root(struct xml_handle *handle_p) /* go to rootlevel and delete everything beneath */
{
  if(handle_p==NULL)  return;

  while(handle_p->child_handle_p!=NULL)
  {
    handle_p = handle_p->child_handle_p;
  }

  while(handle_p->level!=0)
  {
    if(handle_p->elementname!=NULL)  s_free(handle_p->elementname);
    if(handle_p->attribute!=NULL)  s_free(handle_p->attribute);
    if(handle_p->tag_search_result!=NULL)  s_free(handle_p->tag_search_result);

    handle_p = handle_p->parent_handle_p;

    s_free(handle_p->child_handle_p);
  }

  handle_p->child_handle_p = NULL;
}



void xml_go_up(struct xml_handle *handle_p) /* go one level up and delete everything beneath */
{
  int level;

  if(handle_p==NULL)  return;

  while(handle_p->child_handle_p!=NULL)
  {
    handle_p = handle_p->child_handle_p;
  }

  level = handle_p->level;

  if(level==0)  return;

  level--;

  while(handle_p->level!=level)
  {
    if(handle_p->elementname!=NULL)  s_free(handle_p->elementname);
    if(handle_p->attribute!=NULL)  s_free(handle_p->attribute);
    if(handle_p->tag_search_result!=NULL)  s_free(handle_p->tag_search_result);

    handle_p = handle_p->parent_handle_p;

    s_free(handle_p->child_handle_p);
  }

  handle_p->child_handle_p = NULL;
}




int next_tag(int offset, struct xml_handle *handle_p) /* returns offset after '>' */
{
  int temp, fp1=0, fp2=0, tagstart=0;

  if(handle_p->tag_search_result!=NULL)
  {
    s_free(handle_p->tag_search_result);
  }

  handle_p->tag_search_result = NULL;

  fseek(handle_p->file, offset, SEEK_SET);

  while(1)
  {
    temp = fgetc(handle_p->file);
    if(temp==EOF)
    {
      return(-1);
    }

    if(temp=='<')
    {
      if(tagstart)
      {
        return(-1);
      }

      tagstart = 1;
      fp1 = ftell(handle_p->file);
    }

    if(temp=='>')
    {
      if(!tagstart)
      {
        return(-1);
      }

      offset = ftell(handle_p->file);
      fp2 = offset - 1;

      break;
    }
  }

  if(!fp2)
  {
    return(-1);
  }

  fseek(handle_p->file, fp1, SEEK_SET);

  handle_p->tag_search_result = (char *)s_calloc(1, fp2 - fp1 + 1);
  if(handle_p->tag_search_result==NULL)
  {
    return(-1);
  }

  if(fread(handle_p->tag_search_result, fp2 - fp1, 1, handle_p->file) != 1)
  {
    s_free(handle_p->tag_search_result);
    handle_p->tag_search_result = NULL;
    return(-1);
  }

  handle_p->tag_search_result[fp2 - fp1] = 0;

  return(offset);
}













Generated by  Doxygen 1.6.0   Back to index