// Str.cpp - implementation of simple string class
// CSE374 example hp

#include <cstring>
#include <iostream>
#include "Str.h"

#define TRACE(what)  cout << "Str: " << what << " called" << endl

using namespace std;

// constructors
// create empty string
Str::Str() {
  TRACE("null constructor");
  // allocate empty string
  st = new char[1];
  st[0] = '\0';
}

// create Str from c-string
Str::Str(const char *s) {
  TRACE("c-string constructor");
  int len = strlen(s);
  st = new char[len+1];
  strcpy(st, s);
}

// copy constructor
Str::Str(const Str &s) {
  TRACE("copy constructor");
  int len = strlen(s.st);
  st = new char[len+1];
  strcpy(st, s.st);
}

// destructor
Str::~Str() {
  TRACE("destructor");
  delete [] st;
}

// return length of this string
int Str::length() const {
  TRACE("length");
  return strlen(st);
}

// return a c-string with a copy of the contents of this string
char * Str::c_str() const {
  TRACE("c_str");
  char * result = new char[strlen(st)+1];
  strcpy(result, st);
  return result;
}


// append contents of s to the end of this string
void Str::append(const Str &s) {
  TRACE("append");
  char *newst = new char[strlen(st) + strlen(s.st) + 1];
  strcpy(newst, st);
  strcat(newst, s.st);
  delete [] st;
  st = newst;
}

// string assignment - assign s to this Str and return this Str
// (allows chained assignments like a=b=c; to work properly)
Str & Str::operator=(const Str &s) {
  TRACE("Str assignment");
  // do nothing if trying to assign a string to itself
  if (this == &s) {
    return *this;
  }

  // Allocate space for data if source length is different
  if (strlen(st) != strlen(s.st)) {
    delete [] st;
    st = new char[strlen(s.st)+1];
  }

  // copy characters and return
  strcpy(st, s.st);
  return *this;
}