/*$cb
 *    This file is a part of libopenmhp.
 *
 *    Copyright (C) 2005 Mikko Novaro <miknov@gmail.com>
 *
 *    See main header file (libopenmhp/openmhp.h) for licensing and
 *    contact information.
 $ce*/

#include "parser.hpp"

#include <errno.h>
#include <string.h>

#define BUFFER_LENGTH 500

cXMLParser::cXMLParser(const char *filename) {
  in = fopen(filename, "r");
  readLeftover = 0;
}

cXMLParser::~cXMLParser(void) {
  if (in) fclose(in);
  in = NULL;
}

eSegmentType cXMLParser::ReadSegment(char *buffer, int bf_size) {
  int bfpos = 0;
  int ch;
  if (readLeftover != 0) ch = readLeftover;
  else ch = fgetc(in);
  readLeftover = 0;
  if (ch == EOF) {
    buffer[0] = 0;
    return ERROR;
  }

  if (ch != '<') { // pc-data
    buffer[bfpos++] = ch;
    while (ch != '<') {
      ch = fgetc(in);
      if (ch == EOF) {
	buffer[0] = 0;
	return ERROR;
      }
      buffer[bfpos++] = (char)ch;
    }
    readLeftover = ch;
    buffer[bfpos-1] = 0;
    return PC_DATA;
  }

  // a tag:
  bool startTag = true;
  while (ch != '>') {
    ch = fgetc(in);
    if (ch == EOF) {
      buffer[0] = 0;
      return ERROR;
    }
    if (bfpos == 0 & ch == '/') startTag = false;
    else buffer[bfpos++] = (char)ch;
  }
  if (bfpos-2 > 0 & buffer[bfpos-2] == '/') {
    buffer[bfpos-2] = 0;
    return COMBO_TAG;
  }
  else {
    buffer[bfpos-1] = 0;
    if (startTag) return START_TAG;
    else return END_TAG;
  }

  return ERROR;
}

int cXMLParser::Parse() {
  char *buffer = new char[BUFFER_LENGTH];
  int error = 0;
  int depth = 0;
  eSegmentType readType;

  /* NOTE: depth >= 0 means, that XML data MUST begin with a start
     tag. */
  while (depth >= 0 & !error) {
    readType = ReadSegment(buffer, BUFFER_LENGTH);

    switch (readType) {
    case START_TAG:
      StartElement(buffer, NULL);
      depth++;
      break;
      
    case END_TAG:
      EndElement(buffer);
      depth--;
      break;

    case COMBO_TAG:
      StartElement(buffer, NULL);
      EndElement(buffer);
      break;

    case PC_DATA:
      Characters(buffer, strlen(buffer));
      break;

    case ERROR:
      error = -1;
      break;

    default:
      break;
    }
  }
  delete buffer;
  return error;
}

void cXMLParser::Characters(const char *ch, int len) {
}

void cXMLParser::StartElement(const char *name, const char **attrs) {
}

void cXMLParser::EndElement(const char *name) {
}
