/* Copyright (C) 2002-2003, CompHEP Collaboration
 * Author: Alexander Sherstnev
 *----------------------------------------------
 *
 * $Id: tag_parser.c,v 1.10 2003/11/01 21:45:32 kryukov Exp $
 *
 * $Log: tag_parser.c,v $
 * Revision 1.10  2003/11/01 21:45:32  kryukov
 * Copyright record
 *
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tag_reader.h"
#include "tag_parser.h"

/**************************************************/
void
str_cpy (char *src, char *dest)
{
  int i, len;
  char *temp;

  len = strlen (dest);
  temp = malloc (len * sizeof (char));
  for (i = 0; i < len - 1; i++)
    {
      temp[i] = dest[i + 1];
    }
  strncpy (src, temp, len - 2);
}


/**************************************************/
int
intlen (int src)
{
  int i = 0;
  int digit = 1;

  while (abs (src / digit) >= 1.0)
    {
      digit *= 10;
      i++;
    }
  return i;
}


/**************************************************/
static int
command_parser (char *str, string_comnd * com)
{
  int k, j = 0;
  int char_switch = 0;
  int len, namlen, vallen;

  len = strlen (str);
  for (k = 0; k < len; k++)
    {
      if (str[k] == '=')
        namlen = k;
    }

  vallen = len - namlen - 1;
  if (namlen > MAX_COMMAND_LENTH || vallen > MAX_COMMAND_LENTH)
    {
      fprintf (stderr, "Error:problems in command_parser function\n");
      return -1;
    }
  for (k = 0; k < namlen; k++)
    {
      if (str[k] != 32)
        com->name[j++] = str[k];
    }

  j = 0;
  for (k = namlen + 1; k < len; k++)
    {
      if (39 == str[k])
        {
          char_switch++;
          char_switch = char_switch % 2;
        }
      if (str[k] != 32 || char_switch)
        com->value[j++] = str[k];
    }
  com->name[namlen] = '\0';
  com->value[vallen] = '\0';
  return 0;
}


/**************************************************/
int
get_tag (int first, tags * base, char *name)
{
  int i, n;

  n = base->number_of_tags;
  if (first <= n)
    {
      for (i = first; i < n; i++)
        {
          if (!strcmp (base->tag[i]->tagname, name))
            {
              return i;
            }
        }
    }
  return -1;
}


/**************************************************/
int
get_tag_with1com (int first, tags * base, middlestr tagname, string_comnd * com)
{
  int i, j, n;
  string_comnd temp;

  n = base->number_of_tags;
  if (first <= n)
    {
      for (i = first; i < n; i++)
        {
          if (!strcmp (base->tag[i]->tagname, tagname))
            {
              for (j = 0; j < base->tag[i]->tagsize; j++)
                {
                  command_parser (base->tag[i]->commands[j], &temp);
                  if (!strcmp (com->name, temp.name))
                    {
                      strcpy (com->value, temp.value);
                      return i;
                    }
                }
            }
        }
    }
  return -1;
}


/**************************************************/
int
get_tag_with_exactcom (int first, tags * base, middlestr tagname, string_comnd * com)
{
  int i, j, n;
  string_comnd temp;

  n = base->number_of_tags;
  if (first <= n)
    {
      for (i = first; i < n; i++)
        {
          if (!strcmp (base->tag[i]->tagname, tagname))
            {
              for (j = 0; j < base->tag[i]->tagsize; j++)
                {
                  command_parser (base->tag[i]->commands[j], &temp);
                  if (!strcmp (com->name, temp.name) && !strcmp (com->value, temp.value))
                    {
                      return i;
                    }
                }
            }
        }
    }
  return -1;
}


/**************************************************/
int
get_tag_with_exact2com (int first, tags * base, middlestr tagname, string_comnd * com1, string_comnd * com2)
{
  int i, j, n;
  int in[2];
  int stop = 1;
  string_comnd temp;

  n = base->number_of_tags;
  if (first > n)
    {
      return -1;
    }

  i = first - 1;
  while (stop)
    {
      i++;
      if (!strcmp (base->tag[i]->tagname, tagname))
        {
          in[0] = 0;
          in[1] = 0;
          for (j = 0; j < base->tag[i]->tagsize; j++)
            {
              command_parser (base->tag[i]->commands[j], &temp);
              if (!strcmp (com1->name, temp.name) && !strcmp (com1->value, temp.value))
                in[0] = i;
              if (!strcmp (com2->name, temp.name) && !strcmp (com2->value, temp.value))
                in[1] = i;
            }
          if ((in[0] && in[1]) || i == n)
            {
              stop = 0;
            }
        }
    }

  if (in[0] && in[1])
    {
      return in[0];
    }
  else
    {
      return -1;
    }
}


/**************************************************/
int
tag_contain_com (string_comnd * com, elementary_tag * t)
{
  int i;
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (com->name, temp.name))
        {
          strcpy (com->value, temp.value);
          return i;
        }
    }
  return 0;
}


/**************************************************/
int
tag_contain_exactcom (string_comnd com, elementary_tag * t)
{
  int i;
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (com.name, temp.name) && !strcmp (com.value, temp.value))
        {
          return 1;
        }
    }
  return 0;
}


/**************************************************/
int
add_com (string_comnd com, elementary_tag * t)
{
  int i;
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (com.name, temp.name))
        {
          return -1;
        }
    }
  i = strlen (com.name) + strlen (com.value) + 3;
  t->tagsize += 1;
  t->commands = realloc (t->commands, t->tagsize * sizeof (char *));
  t->commands[t->tagsize - 1] = malloc (i * sizeof (char));
  sprintf (t->commands[t->tagsize - 1], "%s=%s", com.name, com.value);
  return 1;
}


/**************************************************/
int
remove_com (char *cname, elementary_tag * t)
{
  int i, j;
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (cname, temp.name))
        {
          t->tagsize -= 1;
          for (j = i; j < t->tagsize; j++)
            {
              t->commands[j] = realloc (t->commands[j], strlen (t->commands[j + 1]) * sizeof (char));
              strcpy (t->commands[i], t->commands[j + 1]);
            }
          t->commands = realloc (t->commands, t->tagsize * sizeof (char *));
          return 1;
        }
    }
  return -1;
}


/**************************************************/
int
add_tag (elementary_tag * tag, tags * base)
{
  int i;

  for (i = 0; i < base->number_of_tags; i++)
    {
      if (!strcmp (base->tag[i]->tagname, tag->tagname))
        {
          return -1;
        }
    }
  base->number_of_tags += 1;
  base->tag = realloc (base->tag, base->number_of_tags * sizeof (elementary_tag));
  base->tag[base->number_of_tags - 1] = tag;
  return 1;
}


/**************************************************/
int
remove_tag (char *tname, tags * base)
{
  int i, j;

  for (i = 0; i < base->number_of_tags; i++)
    {
      if (!strcmp (base->tag[i]->tagname, tname))
        {
          base->number_of_tags -= 1;
          for (j = i; j < base->number_of_tags; j++)
            {
              base->tag[j] = base->tag[j + 1];
            }
          base->tag = realloc (base->tag, base->number_of_tags * sizeof (elementary_tag));
          return 1;
        }
    }
  return -1;
}


/**************************************************/
int
get_ival (int n, char *cname, elementary_tag * t)
{
  int i;
  int res;
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (cname, temp.name))
        {
          res = atoi (temp.value);
          return res;
        }
    }
  return -1;
}


/**************************************************/
double
get_fval (int n, char *cname, elementary_tag * t)
{
  int i;
  double res;
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (cname, temp.name))
        {
          res = atof (temp.value);
          return res;
        }
    }
  return -1.0;
}


/**************************************************/
char *
get_cval (int n, char *cname, elementary_tag * t)
{
  int i;
  char *dummy = "";
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (cname, temp.name))
        {
          char *res = malloc (strlen (temp.value) * sizeof (char));

          strcpy (res, temp.value);
          return res;
        }
    }
  return dummy;

}


/**************************************************/
int
replace_com (string_comnd com, elementary_tag * t)
{
  int i;
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (com.name, temp.name))
        {
          if (!(t->commands[i]))
            free (t->commands[i]);
          t->commands[i] = malloc ((strlen (com.name) + strlen (com.value) + 2) * sizeof (char));
          sprintf (t->commands[i], "%s=%s", com.name, com.value);
          return i;
        }
    }
  return -1;
}


/**************************************************/
int
change_ival (int newval, int shift, string_comnd com, elementary_tag * t)
{
  int i, j;
  int len;
  char *format;
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (com.name, temp.name))
        {
          len = strlen (com.name) + shift + intlen (newval) + 1;
          if (!(t->commands[i]))
            free (t->commands[i]);
          t->commands[i] = malloc (len * sizeof (char));
          format = malloc ((shift + 5) * sizeof (char));
          strcpy (format, "%s=");
          for (j = 0; j < shift; j++)
            format[j + 3] = ' ';
          format[shift + 3] = '\0';
          strcat (format, "%i");
          sprintf (t->commands[i], format, temp.name, newval);
          return 1;
        }
    }
  return -1;
}


/**************************************************/
int
change_fval (double newval, string_comnd com, elementary_tag * t)
{
  int i;
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (com.name, temp.name))
        {
          if (!(t->commands[i]))
            free (t->commands[i]);
          t->commands[i] = malloc ((strlen (com.name) + 13) * sizeof (char));
          sprintf (t->commands[i], "%s=%.5E", com.name, newval);
          return 1;
        }
    }
  return -1;
}


/**************************************************/
int
change_cval (char *newval, string_comnd com, elementary_tag * t)
{
  int i;
  string_comnd temp;

  for (i = 0; i < t->tagsize; i++)
    {
      command_parser (t->commands[i], &temp);
      if (!strcmp (com.name, temp.name))
        {
          if (!(t->commands[i]))
            free (t->commands[i]);
          t->commands[i] = malloc ((strlen (com.name) + strlen (newval) + 2) * sizeof (char));
          sprintf (t->commands[i], "%s=%s", com.name, newval);
          return 1;
        }
    }
  return -1;
}

/**************************************************/
int
event_parser (char *in, char **eventword)
{
  int i, n = 0;
  int len, fulllen;
  int last = 0;

  fulllen = strlen (in);
  while (last < fulllen)
    {
      char *st = strchr (in, ':');
      if (!st)
        {
          fprintf (stderr, "Error! an event does not contain colon!\n");
          return 1;
        }
      len = fulllen - strlen (st);
      eventword[n] = malloc ((len - last + 1) * sizeof (char));

      for (i = last; i < len; i++)
        eventword[n][i - last] = in[i];
      eventword[n][len - last + 1] = '\0';

      last = len + 1;
      in[len] = '_';

      n++;
    }
  return 0;
}
