/* cstring.c

   David Beazley  */

#include "cstring.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>

String *new_String(const char *cs) {
  String *s;
  String t;

  s = (String *) malloc(sizeof(String));
  if (!s) return 0;

  if (!cs) cs = "";
  
  s->text = (char *) malloc(strlen(cs)+1);
  if (!s->text) {
    free(s);
    return 0;
  }
  strcpy(s->text,cs);
  s->len = strlen(cs);
  s->maxlen = s->len;
}

String *init_String(String *s, const char *cs) {
  int  len;

  assert(s);
  assert(cs);

  len = strlen(cs);
  if (len > s->len) {
    char *n;
    n = (char *) realloc(s->text,len+1);
    if (!n) {
      return 0;
    }
    s->maxlen = len;
    s->text = n;
  }
  strcpy(s->text,cs);
  s->len = len;
  return s;
}

void delete_String(String *s) {
  if (!s) return;

  if (s->text) {
    free(s->text);
  }
  free(s);
}

String *copy_String(const String *s) {
  assert(s);
  return new_String(s->text);
}

int String_len(const String *s) {
  assert(s);
  return s->len;
}

const char *String_cstr(const String *s) {
  assert(s);
  return (const char *) s->text;
}

int String_strcmp(const String *s, const String *t) {
  assert(s);
  assert(t);
  return strcmp(s->text,t->text);
}

int String_strstr(const String *s, const String *t) {
  char *f;

  assert(s != NULL);
  assert(t != NULL);

  f = strstr(s->text,t->text);
  if (!f) return -1;
  
  return (int) (f-s->text);
}

int String_strchr(const String *s, char c) {
  char *f;
  assert(s);

  f = strchr(s->text,c);
  if (!f) return -1;
  return (int) (f-s->text);
}

String *String_getslice(String *s, int first, int last) {
  String *t;
  int n;
  char  temp;

  assert(s);
  assert((first >= 0) && (first < s->len));
  assert((last <= s->len));
  assert(last >= first);

  temp = s->text[last];
  s->text[last] = 0;

  t = new_String(s->text+first);
  s->text[last] = temp;
  return t;
}

String *String_strcat(String *s, const String *t) {
  int newlen;

  assert(s);
  assert(t);

  newlen = s->len + t->len;
  if (newlen > s->maxlen) {
    char *n = (char *) realloc(s->text,newlen+1);
    if (!n) return 0;
    s->text = n;
    s->maxlen = newlen;
  }
  strcpy(s->text+s->len,t->text);
  s->len = newlen;
  return s;
}

int String_readline(String *s, FILE *f, int max) {
  char buffer[1000];
  int  nread = 0;
  int  n;

  String *tmp;

  assert(s);
  assert(f);

  tmp = new_String("");

  /* Clear the string */
  init_String(s,"");

  while (max != 0) {
    char *c;

    n = ((max+1) > 1000) ? 1000 : (max+1);
    if (n <= 0) n = 1000;
    c = fgets(buffer, n, f);
    if (!c) {
      delete_String(tmp);
      if (nread) return nread;
      else return -1;
    }

    /* Append the buffer */
    String_strcat(s,init_String(tmp,buffer));

    /* Adjust max */

    max -= strlen(buffer);

    /* Adjust number of bytes read */
    nread += strlen(buffer);

    /* Look for newline */
    if (strchr(buffer,'\n')) break;
  }
  delete_String(tmp);
  return nread;
}
