/*

                                   _JNJ`                        
                               .JNMH`                           
                              JMMF`       `;.                   
                            .NMM)          `MN.                 
                            MMM)            (MML                
                           (MMM`             MMML               
                     M  I  D  N  I  G  H  T    C  o  D  E       
                           (NMMF             MHNH               
                            NMML            .MMM                
                             NMML          .NMH                 
                              4MMNL       .#F                   
                               `4HNNL_   `                      
                                   `"""`                        

                          Copyright (C) 2004-2007
       "Ian (Larry) Latter" <ian dot latter at midnightcode dot org>

    Midnight Code is a registered trademark of Ian Latter.

    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, and mirrored at the Midnight Code web
    site; as at version 2 of the License only.
  
    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
    (version 2) along with this program; if not, write to the Free
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA, or see http://midnightcode.org/gplv2.txt

*/

/* midnightcode-abnf.c :: Midnight Code ABNF (RFC2234) library		*/

/* Includes software to support RFCs :: 2234 */


#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <ctype.h>
#include <arpa/inet.h>

#include "preferences.h"
#include "midnightcode-abnf.h"



int
midnightcode_abnf_parse(char *haystack, int charset) {
  char * needle;
  int charn;


  needle = haystack;
  charn = 0;
  while(*needle) {

    switch(charset) {
      case MIDNIGHTCODE_PARSE_CHARSET_ALPHA:
        if(*needle < 65 || (*needle > 90 && *needle < 97) ||
          *needle > 122)
          return charn;
        break;

      case MIDNIGHTCODE_PARSE_CHARSET_NUMERIC:
        if(*needle < 48 || *needle > 57)
          return charn;
        break;
 
      case MIDNIGHTCODE_PARSE_CHARSET_ALPHANUMERIC:
        if(*needle < 48 || ( *needle > 57 && *needle < 65 ) || 
          (*needle > 90 && *needle < 97) || *needle > 122)
          return charn;
        break;

      case MIDNIGHTCODE_PARSE_CHARSET_ABNFVCHAR:
      case MIDNIGHTCODE_PARSE_CHARSET_PRINTABLE:
        if(*needle < 32 || *needle > 126)
          return charn;
        break;

      default:
        return -1;

    }

    charn++;
  }

  return 0;
}



int
midnightcode_parse_yesno(char *string_buf, int default_return) {
  int string_len;


  string_len = strlen(string_buf);

  switch(string_len) {
    case 7:
      if(strcasecmp(string_buf, "disable") == 0)
        return 0;
      break;

    case 6:
      if(strcasecmp(string_buf, "enable") == 0)
        return 1;
      break;

    case 5:
      if(strcasecmp(string_buf, "false") == 0)
        return 0;
      break;

    case 4:
      if(strcasecmp(string_buf, "true") == 0)
        return 1;
      break;

    case 3:
      if(strcasecmp(string_buf, "yes") == 0)
        return 1;
      if(strcasecmp(string_buf, "yep") == 0)
        return 1;
      if(strcasecmp(string_buf, "yeh") == 0)
        return 1;
      if(strcasecmp(string_buf, "yay") == 0)
        return 1;
      if(strcasecmp(string_buf, "nup") == 0)
        return 0;
      if(strcasecmp(string_buf, "nah") == 0)
        return 0;
      if(strcasecmp(string_buf, "nay") == 0)
        return 0;
      if(strcasecmp(string_buf, "off") == 0)
        return 0;
      break;

    case 2:
      if(strcasecmp(string_buf, "on") == 0)
        return 1;
      if(strcasecmp(string_buf, "no") == 0)
        return 0;
      break;

    case 1:
      if(strcasecmp(string_buf, "y") == 0)
        return 1;
      if(strcasecmp(string_buf, "t") == 0)
        return 1;
      if(strcasecmp(string_buf, "1") == 0)
        return 1;
      if(strcasecmp(string_buf, "n") == 0)
        return 0;
      if(strcasecmp(string_buf, "f") == 0)
        return 0;
      if(strcasecmp(string_buf, "0") == 0)
        return 0;
      break;

  }

  return default_return;
}



int
midnightcode_parse_size(long double * capacity, char * scale, int scale_len) {
  long double exa  = 1000000000000000000ULL;
  long double peta = 1000000000000000ULL;
  long double tera = 1000000000000ULL;
  long double giga = 1000000000ULL;
  long double mega = 1000000ULL;
  long double kilo = 1000ULL;
  long double storage, ret_storage;
  char buf[64];
  char * buf_ptr;
  int buf_len;


  buf_ptr = buf;
  buf_len = scale_len;
  if(scale_len > 64)
    buf_len = 64;

  storage = *capacity;

  ret_storage = storage;
  memset(buf, 0, buf_len);
  snprintf(buf, buf_len - 1, "Byte");

  if(storage > kilo) {
    ret_storage = storage / kilo;
    memset(buf, 0, buf_len);
    snprintf(buf, buf_len - 1, "Kilobyte");
  }
  if(storage > mega) {
    ret_storage = storage / mega;
    memset(buf, 0, buf_len);
    snprintf(buf, buf_len - 1, "Megabyte");
  }
  if(storage > giga) {
    ret_storage = storage / giga;
    memset(buf, 0, buf_len);
    snprintf(buf, buf_len - 1, "Gigabyte");
  }
  if(storage > tera) {
    ret_storage = storage / tera;
    memset(buf, 0, buf_len);
    snprintf(buf, buf_len - 1, "Terabyte");
  }
  if(storage > peta) {
    ret_storage = storage / peta;
    memset(buf, 0, buf_len);
    snprintf(buf, buf_len - 1, "Petabyte");
  }
  if(storage > exa) {
    ret_storage = storage / exa;
    memset(buf, 0, buf_len);
    snprintf(buf, buf_len - 1, "Exabyte");
  }

  *capacity = ret_storage;
  snprintf(scale, buf_len - 1, "%s", buf_ptr);
  if(ret_storage > 1)
    strncat(scale, "s", scale_len - strlen(scale));

  return 0;
}



int
midnightcode_parse_trim(char *string_buf, int string_buf_max) {
  char *parse_src;
  char *string_dst;


  parse_src = string_buf;
  while((*parse_src == ' ' || *parse_src == '\t') &&
        parse_src != &string_buf[string_buf_max - 1])
    parse_src++;
  if(parse_src != string_buf) {
    string_dst = string_buf;
    while(parse_src != &string_buf[string_buf_max]) {
      *string_dst = *parse_src;
      parse_src++;
      string_dst++;
    }
    while(string_dst != &string_buf[string_buf_max]) {
      *string_dst = '\0';
      string_dst++;
    }
  }

  parse_src = &string_buf[string_buf_max - 1];
  while((*parse_src == ' ' || *parse_src == '\t' || *parse_src == '\0') &&
        parse_src != string_buf) {
    parse_src--;
  }
  if(parse_src != &string_buf[string_buf_max - 1]) {
    parse_src++;
    string_dst = parse_src;
    while(string_dst != &string_buf[string_buf_max - 1]) {
      *string_dst = '\0';
      string_dst++;
    }
  }

  return 0;
}



int
midnightcode_parse_extmatch(struct midnightcode_parse_extension_t * exts,
                            char * url, int url_len) {
  int ret_i;
  int extn, ext_len;
  int offset;
  struct midnightcode_parse_extension_t * ext;
  char * parse_src;


  ret_i = 0;
  offset = 0;
  ext_len = 0;
  parse_src = url;

  if(url_len > (int)strlen(url))
    return -1;

  for(ext = exts, extn = 0; ext[extn].ext != NULL; extn++) {
    ext_len = strlen(ext[extn].ext);
    offset = url_len - ext_len - 1; 
    if(offset < 0)
      continue;
    parse_src = (char *)(url + offset);
    if(*parse_src == '.') {
      parse_src++;
      if(strncasecmp(parse_src, ext[extn].ext, ext_len) == 0) {
        ret_i = extn;
        break;
      }
    }
  }

  return ret_i;
}



int
midnightcode_parse_exttype(char *url, int url_len, int type) {
  int ret_i;

  /* TODO: Turn these extensions into an extended mime-types function */

  struct midnightcode_parse_extension_t set_arc[] = {
    { "bz" },
    { "bz2" },
    { "bzip" },
    { "deb" },
    { "gz" },
    { "gzip" },
    { "lzh" },
    { "rar" },
    { "rpm" },
    { "tar" },
    { "tbz" },
    { "tgz" },
    { "z" },
    { "zip" },
    { 0 }
  };

  struct midnightcode_parse_extension_t set_aud[] = {
    { "au" },
    { "kar" },
    { "mid" },
    { "midi" },
    { "mp2" },
    { "mp3" },
    { "mpga" },
    { "oda" },
    { "ogg" },
    { "ram" },
    { "rm" },
    { "snd" },
    { "wav" },
    { "wmv" },
    { 0 }
  };

  struct midnightcode_parse_extension_t set_doc[] = {
    { "doc" },
    { "chrt" },
    { "eps" },
    { "kil" },
    { "kpr" },
    { "kpt" },
    { "ksp" },
    { "kwd" },
    { "kwt" },
    { "pdf" },
    { "ppt" },
    { "ps" },
    { "txt" },
    { "xht" },
    { "xhtml" },
    { "xls" },
    { "xlt" },
    { "xml" },
    { 0 }
  };

  struct midnightcode_parse_extension_t set_htm[] = {
    { "htm" },
    { "html" },
    { 0 }
  };

  struct midnightcode_parse_extension_t set_pic[] = {
    { "bmp" },
    { "gif" },
    { "jpe" },
    { "jpeg" },
    { "jpg" },
    { "pbm" },
    { "pcx" },
    { "pgm" },
    { "png" },
    { "pnm" },
    { "ppm" },
    { "rgb" },
    { "tif" },
    { "tiff" },
    { "xbm" },
    { "xpm" },
    { "xwd" },
    { 0 }
  };

  struct midnightcode_parse_extension_t set_vid[] = {
    { "avi" },
    { "idx" },
    { "mpeg" },
    { "mpe" },
    { "mpeg2" },
    { "mpg" },
    { "mpg2" },
    { "mov" },
    { "qt" },
    { "ra" },
    { "rm" },
    { "ram" },
    { "srt" },
    { "sub" },
    { "wmv" },
    { "vcd" },
    { 0 }
  };


  ret_i = 0;
  switch(type) {

    case MIDNIGHTCODE_PARSE_EXT_TYPE_HTML:
      ret_i = midnightcode_parse_extmatch(set_htm, url, url_len);
      break;

    case MIDNIGHTCODE_PARSE_EXT_TYPE_DOCUMENT:
      ret_i = midnightcode_parse_extmatch(set_doc, url, url_len);
      break;

    case MIDNIGHTCODE_PARSE_EXT_TYPE_PICTURE:
      ret_i = midnightcode_parse_extmatch(set_pic, url, url_len);
      break;

    case MIDNIGHTCODE_PARSE_EXT_TYPE_VIDEO:
      ret_i = midnightcode_parse_extmatch(set_vid, url, url_len);
      break;

    case MIDNIGHTCODE_PARSE_EXT_TYPE_AUDIO:
      ret_i = midnightcode_parse_extmatch(set_aud, url, url_len);
      break;

    case MIDNIGHTCODE_PARSE_EXT_TYPE_ARCHIVE :
      ret_i = midnightcode_parse_extmatch(set_arc, url, url_len);
      break;

    default:
      break;

  }

  return ret_i;
}



int
midnightcode_parse_strtoarg(char *string_buf, int string_buf_max,
                            char **args, int args_max) {
  char parse_buf[16384];
  char *parse_src, *string_dst;
  int  arg_index;
  int  string_buf_free;
  int  quote_state;


  /* TODO: change 16384 to malloc of string_buf_max + 1 */
  memset(parse_buf, 0, 16384);
  strncpy(parse_buf, string_buf, sizeof(parse_buf) - 1);
  if(strlen(parse_buf) != strlen(string_buf))
    return -1;
  memset(string_buf, 0, string_buf_max);

  if(args_max == 0)
    args_max = 65535;
  if(args_max < 1)
    args_max = 1;
  args[0] = NULL;

  parse_src = parse_buf;
  string_dst = string_buf;
  arg_index = 1;
  args[arg_index] = string_dst;

  string_buf_free = string_buf_max;
  quote_state = 0;

  while(*parse_src != '\0' && string_buf_free > 0 && arg_index < args_max) {

    if(*parse_src == '\\') {
      parse_src++;
      if(*parse_src == '\\') {
        *string_dst = '\\';
      } else if(*parse_src == '"') {
        *string_dst = '"';
      } else if(*parse_src == 'a') {
        *string_dst = '\a';
      } else if(*parse_src == 'b') {
        *string_dst = '\b';
      } else if(*parse_src == 'f') {
        *string_dst = '\f';
      } else if(*parse_src == 'n') {
        *string_dst = '\n';
      } else if(*parse_src == 'r') {
        *string_dst = '\r';
      } else if(*parse_src == 't') {
        *string_dst = '\t';
      } else if(*parse_src == 'v') {
        *string_dst = '\v';
      } else {
        parse_src--;
        *string_dst = *parse_src;
      }
      string_buf_free--;
      string_dst++;

    } else if(*parse_src == '"') {
      quote_state = !quote_state;

    } else if((*parse_src == ' ') || (*parse_src == '\t')) {
      if(quote_state) {
        *string_dst = *parse_src;
        string_buf_free--;
        string_dst++;
      } else {
        while(*parse_src == ' ' || *parse_src == '\t')
          parse_src++;
        parse_src--;
        *string_dst = '\0';
        string_buf_free--;
        string_dst++;
        arg_index++;
        args[arg_index] = string_dst;
      }

    } else {
      *string_dst = *parse_src;
      string_buf_free--;
      string_dst++;

    }
    parse_src++;

  }

  *string_dst = '\0';
  arg_index++;
  args[arg_index] = NULL;

  return arg_index;
}



int
midnightcode_parse_strtovar(void * variable, char * buffer,
                            int length, int value, int type) {
  int  *int_p;
  char *char_p;
  long  *long_p;
  u_long *u_long_p;
  float *float_p;
  double *double_p;
  long double *longdouble_p;
  u_char *uchar_p;
  struct hostent *host_ent;
  struct in_addr in_adr;
  int chrn, dotn, byte_t;


  if((!buffer && type != MIDNIGHTCODE_PARSE_TYPE_NONE) || !variable)
    return -1;

  switch(type) {
    case MIDNIGHTCODE_PARSE_TYPE_NONE:
      int_p = variable;
      *int_p = 1;
      break;

    case MIDNIGHTCODE_PARSE_TYPE_STRING:
      char_p = variable;
      memset(char_p, 0, length);
      strncpy(char_p, buffer, length - 1);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_INT:
      int_p = variable;
      *int_p = (int)strtol(buffer, (char **)NULL, 10);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_LONG:
      long_p = variable;
      *long_p = strtol(buffer, (char **)NULL, 10);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_VAL:
      int_p = variable;
      *int_p = value;
      break;

    case MIDNIGHTCODE_PARSE_TYPE_FLOAT:
      float_p = variable;
      *float_p = (float)strtod(buffer, (char **)NULL);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_DOUBLE:
      double_p = variable;
      *double_p = strtod(buffer, (char **)NULL);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_LONGDOUBLE:
      longdouble_p = variable;
      *longdouble_p = strtold(buffer, (char **)NULL);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_HWADDR:
      uchar_p = variable;
      byte_t = 1;
      dotn = 0;
      for(char_p = buffer; char_p != &buffer[18]; char_p++, byte_t++) {
        if(byte_t == 3) {
          byte_t = 0;
          uchar_p++;
        }
        if(*char_p == '\0')
          break;
        if(byte_t) {
          if(*char_p >= 48 && *char_p <= 57) {
            if(byte_t == 1)
              *uchar_p = ((u_int)(*char_p) - 48) * 16;
            if(byte_t == 2)
              *uchar_p += ((u_int)(*char_p) - 48);

          } else if(*char_p >= 65 && *char_p <= 70) {
            if(byte_t == 1)
              *uchar_p = ((u_int)(*char_p) - 55) * 16;
            if(byte_t == 2)
              *uchar_p += ((u_int)(*char_p) - 55);

          } else if(*char_p >= 97 && *char_p <= 102) {
            if(byte_t == 1)
              *uchar_p = ((u_int)(*char_p) - 87) * 16;
            if(byte_t == 2)
              *uchar_p += ((u_int)(*char_p) - 87);

          } else {
            return -1;

          }
        } else {
          if(*char_p == 58) {
            dotn++;
          } else {
            return -1;
          }
        }
      }
      if(dotn != 5)
        return -1;
      break;

    case MIDNIGHTCODE_PARSE_TYPE_HOST:
      u_long_p = variable;
      if((host_ent = gethostbyname(buffer)) == NULL)
        return -1;
      if(host_ent->h_addrtype != AF_INET)
        return -1;
      memcpy(&in_adr.s_addr, host_ent->h_addr, host_ent->h_length);
      *u_long_p = in_adr.s_addr;
      break;

    case MIDNIGHTCODE_PARSE_TYPE_IP:
      u_long_p = variable;
      if(strlen(buffer) > 16)
        return -1;
      char_p = buffer;
      for(dotn = 0, chrn = 0; chrn < 17; chrn++) {
        char_p = buffer;
        char_p += chrn;
        if(*char_p == '\0')
          break;
        if(!(*char_p >= 48 && *char_p <= 57) && *char_p != 46)
          return -1;
        if(*char_p == '.')
          dotn++;
      }
      if(dotn != 3)
        return -1;
      if((host_ent = gethostbyname(buffer)) == NULL)
        return -1;
      if(host_ent->h_addrtype != AF_INET)
        return -1;
      memcpy(&in_adr.s_addr, host_ent->h_addr, host_ent->h_length);
      *u_long_p = in_adr.s_addr;
      break;

    default:
      return -1;
      break;

  }

  return 0;
}



int
midnightcode_parse_vartostr(char * buffer, void * variable,
                            int length, int value, int type) {
  int  *int_p;
  char *char_p;
  long  *long_p;
  u_long *u_long_p;
  float *float_p;
  double *double_p;
  long double *longdouble_p;
  u_char *uchar_p;

                          
  if(!buffer || !variable)
    return -1;

  memset(buffer, 0, length);

  switch(type) {
    case MIDNIGHTCODE_PARSE_TYPE_NONE:
      /* TODO: Is value needed in this function? */
      value = 0;
      break;

    case MIDNIGHTCODE_PARSE_TYPE_STRING:
      char_p = variable;
      strncpy(buffer, char_p, length - 1);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_INT:
      int_p = variable;
      snprintf(buffer, length - 1, "%d", *int_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_LONG:
      long_p = variable;
      snprintf(buffer, length - 1, "%ld", *long_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_VAL:
      int_p = variable;
      snprintf(buffer, length - 1, "%d", *int_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_FLOAT:
      float_p = variable;
      snprintf(buffer, length - 1, "%f", *float_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_DOUBLE:
      double_p = variable;
      snprintf(buffer, length - 1, "%f", *double_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_LONGDOUBLE:
      longdouble_p = variable;
      snprintf(buffer, length - 1, "%.0Lf", *longdouble_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_HWADDR:
      uchar_p = variable;
      snprintf(buffer, length - 1, "%02X:%02X:%02X:%02X:%02X:%02X",
        *uchar_p, *(uchar_p + 1), *(uchar_p + 2), *(uchar_p + 3),
        *(uchar_p + 4), *(uchar_p + 5));
      break;

    case MIDNIGHTCODE_PARSE_TYPE_HOST:
      u_long_p = variable;
      inet_ntop(AF_INET, u_long_p, buffer, length - 1);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_IP:
      u_long_p = variable;
      inet_ntop(AF_INET, u_long_p, buffer, length - 1);
      break;

    default:
      return -1;
      break;

  }
  
  return 0;
}



int
midnightcode_parse_unserialize(void * variable, char * buffer,
                            int length, int value, int type) {
  int chrn;
  char *buff_p, *store_p;
  int buff_len, str_len, ret_i;


  if(!buffer || !variable)
    return -1;

  store_p = buffer;
  buff_p = buffer;
  chrn = 0;
  str_len = 0;
  buff_len = 0;
  ret_i = 0;

  switch(type) {
    case MIDNIGHTCODE_PARSE_TYPE_NONE:
      break;

    case MIDNIGHTCODE_PARSE_TYPE_STRING:
    case MIDNIGHTCODE_PARSE_TYPE_HWADDR:
    case MIDNIGHTCODE_PARSE_TYPE_HOST:
    case MIDNIGHTCODE_PARSE_TYPE_IP:
      if(*buff_p != 's')
        return -1;
      buff_p++;
      if(*buff_p != ':')
        return -1;
      buff_p++;
      store_p = buff_p;
      buff_len = 2;
      for(; *buff_p != ':' && *buff_p != '\0'; buff_p++, buff_len++);
      if(*buff_p != ':')
        return -1;
      *buff_p = '\0';
      str_len = (int)strtol(store_p, (char **)NULL, 10);
      *buff_p = ':';
      if(type != MIDNIGHTCODE_PARSE_TYPE_HWADDR) {
        if(str_len > (length - 1) || str_len < 0)
          return -1;
      }
      buff_p++;
      if(*buff_p != '"')
        return -1;
      buff_p++;
      buff_len += 2;
      store_p = buff_p;
      if(*(buff_p + str_len) != '\"' && *(buff_p + str_len + 1) != ';')
        return -1;
      *(buff_p + str_len) = '\0';
      break;

    case MIDNIGHTCODE_PARSE_TYPE_INT:
    case MIDNIGHTCODE_PARSE_TYPE_LONG:
      if(*buff_p != 'i')
        return -1;
      buff_p++;
      if(*buff_p != ':')
        return -1;
      buff_p++;
      store_p = buff_p;
      buff_len = 2;
      for(; *buff_p != ';' && *buff_p != '\0'; buff_p++, buff_len++);
      if(*buff_p != ';')
        return -1;
      *buff_p = '\0';
      break;

    case MIDNIGHTCODE_PARSE_TYPE_FLOAT:
    case MIDNIGHTCODE_PARSE_TYPE_DOUBLE:
    case MIDNIGHTCODE_PARSE_TYPE_LONGDOUBLE:
      if(*buff_p != 'd')
        return -1;
      buff_p++;
      if(*buff_p != ':')
        return -1;
      buff_p++;
      store_p = buff_p;
      buff_len = 2;
      for(; *buff_p != ';' && *buff_p != '\0'; buff_p++, buff_len++);
      if(*buff_p != ';')
        return -1;
      *buff_p = '\0';
      break;

    default:
      return -1;
      break;

  }

  switch(type) {
    case MIDNIGHTCODE_PARSE_TYPE_STRING:
    case MIDNIGHTCODE_PARSE_TYPE_HWADDR:
    case MIDNIGHTCODE_PARSE_TYPE_HOST:
    case MIDNIGHTCODE_PARSE_TYPE_IP:
      if(midnightcode_parse_strtovar(variable, store_p, str_len + 1, 0, type))
        ret_i = -1;
      break;

    default:
      if(midnightcode_parse_strtovar(variable, store_p, 0, value, type))
        ret_i = -1;
      break;
  }

  switch(type) {
    case MIDNIGHTCODE_PARSE_TYPE_NONE:
      break;

    case MIDNIGHTCODE_PARSE_TYPE_STRING:
    case MIDNIGHTCODE_PARSE_TYPE_HWADDR:
    case MIDNIGHTCODE_PARSE_TYPE_HOST:
    case MIDNIGHTCODE_PARSE_TYPE_IP:
      *(buff_p + str_len) = '\"';
      buff_len += str_len + 2;
      break;

    case MIDNIGHTCODE_PARSE_TYPE_INT:
    case MIDNIGHTCODE_PARSE_TYPE_LONG:
      *buff_p = ';';
      buff_len++;
      break;

    case MIDNIGHTCODE_PARSE_TYPE_FLOAT:
    case MIDNIGHTCODE_PARSE_TYPE_DOUBLE:
    case MIDNIGHTCODE_PARSE_TYPE_LONGDOUBLE:
      *buff_p = ';';
      buff_len++;
      break;

  }

  if(!ret_i)
    ret_i = buff_len;

  return ret_i;
}



int
midnightcode_parse_serialize(char * buffer, void * variable,
                             int length, int value, int type) {
  int  *int_p;
  char *char_p;
  long  *long_p;
  u_long *u_long_p;
  float *float_p;
  double *double_p;
  long double *longdouble_p;
  u_char *uchar_p;


  if(!buffer || !variable)
    return -1;

  memset(buffer, 0, length);

  switch(type) {
    case MIDNIGHTCODE_PARSE_TYPE_NONE:
      /* TODO: Is value needed in this function? */
      value = 0;
      break;

    case MIDNIGHTCODE_PARSE_TYPE_STRING:
      char_p = variable;
      snprintf(buffer, length - 1, "s:%d:\"%s\";", strlen(char_p), char_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_INT:
      int_p = variable;
      snprintf(buffer, length - 1, "i:%d;", *int_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_LONG:
      long_p = variable;
      snprintf(buffer, length - 1, "i:%ld;", *long_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_VAL:
      int_p = variable;
      snprintf(buffer, length - 1, "i:%d;", *int_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_FLOAT:
      float_p = variable;
      snprintf(buffer, length - 1, "d:%f;", *float_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_DOUBLE:
      double_p = variable;
      snprintf(buffer, length - 1, "d:%f;", *double_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_LONGDOUBLE:
      longdouble_p = variable;
      snprintf(buffer, length - 1, "d:%.0Lf;", *longdouble_p);
      break;

    case MIDNIGHTCODE_PARSE_TYPE_HWADDR:
      uchar_p = variable;
      snprintf(buffer, length - 1, "s:17:\"%02X:%02X:%02X:%02X:%02X:%02X\";",
        *uchar_p, *(uchar_p + 1), *(uchar_p + 2), *(uchar_p + 3),
        *(uchar_p + 4), *(uchar_p + 5));
      break;

    case MIDNIGHTCODE_PARSE_TYPE_HOST:
      u_long_p = variable;
      snprintf(buffer, length - 1, "s:%d:\"%s\";",
        strlen(inet_ntop(AF_INET, u_long_p, buffer, length - 1)),
        inet_ntop(AF_INET, u_long_p, buffer, length - 1));
      break;

    case MIDNIGHTCODE_PARSE_TYPE_IP:
      u_long_p = variable;
      snprintf(buffer, length - 1, "s:%d:\"%s\";",
        strlen(inet_ntop(AF_INET, u_long_p, buffer, length - 1)),
        inet_ntop(AF_INET, u_long_p, buffer, length - 1));
      break;

    default:
      return -1;
      break;

  }
  
  return 0;
}

