/*
  (c) 1998 netEstate (http://www.netestate.de/, info@netestate.de),
Michael Brunnbauer & Markus Hendel, Gesellschaft fuer Netzwerkkommunikation bR
Am Bluetenanger 8, 80995 Muenchen, Germany

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 2 of the License, or
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "stringlib.h"

/* konstruktor */
string::string() { zgr=0; len=0; }

/* destruktor */
string::~string() { if (zgr) { string_mem-=len; free(zgr); }; }

/* copy-konstruktor */
string::string(string& src)
{
  if (src.zgr)
    {
      zgr=strdup(src.zgr);
      if (!zgr) { log(LOG_FATAL,__FILE__,__LINE__,ERROR_OUT_OF_MEM,NULL); };
      len=src.len;
      string_mem+=len;
    }
  else
    {
      zgr=0;
      len=0;
    };
}

/* = ueberladen */
string& string::operator=(string src)
{
  if (zgr) { string_mem-=len; free(zgr); };
  if (src.zgr)
    {
      zgr=strdup(src.zgr);
      if (!zgr) { log(LOG_FATAL,__FILE__,__LINE__,ERROR_OUT_OF_MEM,NULL); };
      len=src.len;
      string_mem+=len;
    }
  else
    {
      zgr=0;
      len=0;
    };
  return *this;
}

/* [] ueberladen */
char& string::operator[](unsigned long i)
{
  if (!zgr)
    {
      log(LOG_FATAL,__FILE__,__LINE__,ERROR_UNSPECIFIED,
	  "called operator[] for string while string was NULL");
    };

  if (i>=len)
    {
      log(LOG_FATAL,__FILE__,__LINE__,ERROR_VALUE_OUT_OF_RANGE,
	  "Value was: %i / string: %s",i,zgr);
    };
  return zgr[i];
}

/* konversion von char* nach string */
string::string(char* src)
{
  if (src)
    {
      len=strlen(src);
      zgr=(char*) malloc(len+1);
      if (!zgr) { log(LOG_FATAL,__FILE__,__LINE__,ERROR_OUT_OF_MEM,NULL); };
      memcpy(zgr,src,len);
      zgr[len]=0;
      string_mem+=len;
    }
  else
    {
      zgr=0;
      len=0;
    };
}

/* konversion von string nach char* */
string::operator char*()
{
  if (!zgr)
    {
      log(LOG_FATAL,__FILE__,__LINE__,ERROR_UNSPECIFIED,
	  "konversion from string to char* while string was NULL");
    };
  return zgr;
}

/* einzelne woerter */
string string::word(unsigned int i)
{
  char* rueck;
  string rueck1;

  if (!zgr)
    {
      log(LOG_FATAL,__FILE__,__LINE__,ERROR_UNSPECIFIED,
          "called word() for string while string was NULL");
    };

  rueck=zgr;
  while (i)
    {
      if (!(rueck=strchr(rueck,' ')))
	{
	  log(LOG_FATAL,__FILE__,__LINE__,ERROR_VALUE_OUT_OF_RANGE,
	      "Value was: %i /string: %s",i,rueck);
	};
      rueck++;
      i--;
    };

  rueck1=rueck;
  if (strchr(rueck1.zgr,' ')) { strchr(rueck1.zgr,' ')[0]=0; };

  return rueck1;
}

/* wieviele woerter ? */
unsigned int string::words()
{
  char* zgr1;
  unsigned int i;

  if (!zgr)
    {
      log(LOG_FATAL,__FILE__,__LINE__,ERROR_UNSPECIFIED,
          "called words() for string while string was NULL");
    };
 
  zgr1=zgr;i=1;
  while ((zgr1=strchr(zgr1,' '))) { zgr1++; i++; };
  return i;
}

/* + ueberladen */
string operator+(string string1,string string2)
{
  string rueck;
  unsigned long size;

  if (!string1.zgr || !string2.zgr)
    {
      log(LOG_FATAL,__FILE__,__LINE__,ERROR_WRONG_ARGUMENT,
	  "String argument for string operator+() was NULL");
    };

  size=string1.len+string2.len;
  rueck.zgr=(char*) malloc(size+1);
  if (!rueck.zgr) { log(LOG_FATAL,__FILE__,__LINE__,ERROR_OUT_OF_MEM,NULL); };
  memcpy(rueck.zgr,string1.zgr,string1.len);
  memcpy(rueck.zgr+string1.len,string2.zgr,string2.len);
  rueck.zgr[size]=0;
  rueck.len=size;
  return rueck;
}

/* += ueberladen */
string& string::operator+=(string string1)
{
  unsigned long size;

  if (!string1.zgr)
    {
      log(LOG_FATAL,__FILE__,__LINE__,ERROR_WRONG_ARGUMENT,
          "String argument for string operator+=() was NULL");
    };

  if (string1.len)
    {
      size=len+string1.len;
      if (!(zgr=(char*) realloc((void*) zgr,size+1)))
	{ log(LOG_FATAL,__FILE__,__LINE__,ERROR_OUT_OF_MEM,NULL); };
      memcpy(zgr+len,string1.zgr,string1.len);
      zgr[size]=0;
      string_mem-=len;
      string_mem+=size;
      len=size;
    };
  return *this;
}

/* == ueberladen */
int operator==(string string1,string string2)
{
  if (!string1.zgr || !string2.zgr)
    {
      log(LOG_FATAL,__FILE__,__LINE__,ERROR_WRONG_ARGUMENT,
          "String argument for string operator==() was NULL");
    };
  return (!strcmp(string1.zgr,string2.zgr));
}

/* != ueberladen */
int operator!=(string string1,string string2)
{
  if (!string1.zgr || !string2.zgr)
    {
      log(LOG_FATAL,__FILE__,__LINE__,ERROR_WRONG_ARGUMENT,
          "String argument for string operator!=() was NULL");
    };
  return (strcmp(string1.zgr,string2.zgr));
}

/* << ueberladen fuer die ausgabe in streams */
ostream& operator<<(ostream& os, string& src)
{
  if (!src.zgr)
    {
      log(LOG_FATAL,__FILE__,__LINE__,ERROR_WRONG_ARGUMENT,
	  "called operator<< for string while string was NULL");
    };

  os << src.zgr;
  return os;
}

bool defined(string& data)
{
  return (bool) data.zgr;
}

unsigned long hash(string& name)
{
  unsigned char hashsum=0;
  unsigned long i=0;
  while (name.zgr[i]) { hashsum+=(unsigned char) name.zgr[i++]; };
  return (unsigned long) hashsum;
}

