//--------------------------------------------------------------------
//
//  Laboratory 3                                          stradt.cpp
//
//  SOLUTION: Array implementation of the Stradt ADT
//
//--------------------------------------------------------------------

#include <iostream.h>
#include <iomanip.h>
#include <assert.h>
#include <string.h>
#include "stradt.h"

//--------------------------------------------------------------------

Stradt:: Stradt ( int numChars )

// Creates an empty string. Allocates enough memory for numChars+1
// characters (defaults to 1 character).

  : bufferSize(numChars+1)

{
    buffer = new char [ bufferSize ];   // Allocate memory for buffer
    assert ( buffer != 0 );             // Confirm allocation
    buffer[0] = '\0';                   // Set string to empty
}

//--------------------------------------------------------------------

Stradt:: Stradt ( const char *charSeq )

// Creates a string containing the delimited sequence of characters
// charSeq. Allocates enough memory for this string.

{
    bufferSize = strlen(charSeq) + 1;   // Account for null

    buffer = new char [ bufferSize ];   // Allocate memory
    assert ( buffer != 0 );

    strcpy(buffer,charSeq);             // Copy the string
}

//--------------------------------------------------------------------

Stradt:: ~Stradt ()

// Frees the memory used by a string.

{
    delete [] buffer;
}

//--------------------------------------------------------------------

int Stradt:: length () const

// Returns the number of characters in a string (excluding the
// null character).

{
    return strlen(buffer);
}

//--------------------------------------------------------------------

char Stradt:: operator [] ( int n ) const

// Returns the nth character in a string -- where the characters are
// numbered beginning with zero.

{
    if ( n >= 0  &&  n <= length() )
       return buffer[n];
    else
       return '\0';
}

//--------------------------------------------------------------------

void Stradt:: operator = ( const Stradt &rightString )

// Assigns rightString to a string.

{
    int rlen = rightString.length();   // Length of rightString

    if ( rlen >= bufferSize )          // If rightString will not fit
    {
       delete [] buffer;                    // Release buffer and
       bufferSize = rlen + 1;               //  allocate a new
       buffer = new char [ bufferSize ];    //  (larger) buffer
       assert ( buffer != 0 );
    }

    strcpy(buffer,rightString.buffer);   // Copy rightString
}

//--------------------------------------------------------------------

void Stradt:: clear ()

// Clears a string -- i.e., makes it empty. The buffer size
// remains unchanged.

{
    buffer[0] ='\0';
}

//--------------------------------------------------------------------

void Stradt:: showStructure () const

// Outputs the characters in a string. This operation is intended for
// testing/debugging purposes only.

{
    int j;   // Loop counter

    for ( j = 0 ; j < bufferSize ; j++ )
        cout << j << "\t";
    cout << endl;
    for ( j = 0 ; buffer[j] != '\0' ; j++ )
        cout << buffer[j] << "\t";
    cout << "\\0" << endl;
}

//--------------------------------------------------------------------
//
//                        In-lab operations
//
//--------------------------------------------------------------------

istream & operator >> ( istream &input, Stradt &inputString )

// String input function. Extracts a string from istream input and
// returns it in inputString. Returns the state of the input stream.

{
    const int textBufferSize = 256;     // Large (but finite)
    char textBuffer [textBufferSize];   // text buffer

    // Read a string into textBuffer, setw is used to prevent buffer
    // overflow.

    input >> setw(textBufferSize) >> textBuffer;

    // Apply the Stradt(char*) constructor to convert textBuffer to
    // a string. Assign the resulting string to inputString using the
    // assignment operator.

    inputString = textBuffer;

    // Return the state of the input stream.

    return input;
}

//--------------------------------------------------------------------

ostream & operator << ( ostream &output, const Stradt &outputString )

// String output function. Inserts outputString in ostream output.
// Returns the state of the output stream.

{
   output << outputString.buffer;
   return output;
}

//--------------------------------------------------------------------

Stradt:: Stradt ( const Stradt &valueString )

// Copy constructor, creates a copy of valueString. Called whenever
//
//   1) a string is passed to a function using call by value,
//   2) a function returns a string, or
//   3) a string is initialized using another string -- as in the
//      declarations:
//                      Stradt str1("First"),
//                             str2 = str1;

  : bufferSize(valueString.bufferSize)

{
    buffer = new char [bufferSize];      // Allocate memory
    assert ( buffer != 0 );

    strcpy(buffer,valueString.buffer);   // Copy the string
}

//--------------------------------------------------------------------

int operator == ( const Stradt &leftString,
                  const Stradt &rightString )

// Equality relational operator. Returns 1 if leftString is equal to
// rightString. Otherwise returns 0.

{
    return ( strcmp(leftString.buffer,rightString.buffer) == 0 );
}

//--------------------------------------------------------------------

int operator < ( const Stradt &leftString,
                 const Stradt &rightString )

// "Less than" relational operator. Returns 1 if leftString is less
// than rightString. Otherwise returns 0.

{
    return ( strcmp(leftString.buffer,rightString.buffer) < 0 );
}

//--------------------------------------------------------------------

int operator > ( const Stradt &leftString,
                 const Stradt &rightString )

// "Greater than" relational operator. Returns 1 if leftString is
// greater than rightString. Otherwise returns 0.

{
    return ( strcmp(leftString.buffer,rightString.buffer) > 0 );
}
