//------------------------------------------------------------
// $Id: myString.h,v 1.3 2000/05/21 18:43:03 yamauchi Exp $
//------------------------------------------------------------
//  myString.h
// 	IBM の IString クラスは string.h, ctype.h を拡張した形のもので
//	あって、gnu のように awk の関数を実現するという考えではない。
// 	しかし、gnu の String クラスの Regex という正規表現部分を xlC 
// 	によってコンパイルすることは困難なようである。そこで既に GNU 
// 	の String クラスを使っている私としては、ばかばかしい感はあるが、
//	非常に限定された myString クラスを書くことにした。
//	GNU のものが利用できるのならばこのクラスは無用である。
//	また利用できる部分は GNU libg++-2.7.1 を利用させていただいた。
//	
//	Because in sp2 with AIX3.2, I could not use g++ and GNU libg++,
//	but I want to use them. So, I wrote some code for sp2 based on 
//	GNU gcc and libg++.
//	If you can use gcc and libg++, please use them. Gnu code is
//	best, I think.
//	
//	This class is poor.
//
// 	(C) Hitoshi Yamauchi 平成８年８月２４日(土)
//------------------------------------------------------------

#ifndef _myString_h
#define _myString_h 1

#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include "strnew.h"
//------------------------------
// for (M\pi)^2 
//------------------------------
#ifdef MPI2
#include "mpi2exit.h"
static void mystring_exit(int n)
{
    commMpi2_exit(n);
}
#else
static void mystring_exit(int n)
{
    exit(n);
}
#endif

//------------------------------------------------------------
// myString
//------------------------------------------------------------
class myString{
protected:
    int    mLen;
    char  *mpStr;

public:
    // constructors & assignment
    myString(void);
    myString(const myString& x);
    myString(const char* t);
    myString(char c);
    ~myString(void);

    // assignment
    myString& operator =  (const myString&     y);
    myString& operator =  (const char* y);
    myString& operator =  (char        c);

    // compare
    friend int operator==(const myString& x, const myString& y);
    friend int operator!=(const myString& x, const myString& y);
    friend int operator==(const myString& x, const char* t);
    friend int operator!=(const myString& x, const char* t);
    friend int operator==(const char* t, const myString& x);
    friend int operator!=(const char* t, const myString& x);
    
    // concatenation
    myString&  operator+=(const myString&     y); 
    friend myString operator+ (const myString& x, const myString& y);
    
    // conversion
    operator const char*() const	{ return(this->mpStr); }
    const char*    chars() const	{ return(this->mpStr); }

    // IO
    friend ostream& operator<<(ostream& s, const myString& x);
    // status
    unsigned int length(void) const	{ return(this->mLen); }
    int          empty(void) const	{ return(this->mLen == 0); }

    // split string into array res at separators; return number of elements
    friend int splitWithWhite(const myString& x, myString res[], int maxn);
    // get number of words (separator is white space)
    friend int getNumOfWords(const myString& x);
};

//------------------------------
// constructors
//------------------------------
inline myString::
myString(void) 
{
    this->mLen  = 0;
    this->mpStr = strnew("");
}

inline myString::
myString(const myString& rhs) 
{
    this->mLen  = rhs.mLen;
    this->mpStr = strnew(rhs.mpStr);
}

inline myString::
myString(const char* rhs) 
{
    if(rhs == NULL)
    {
	cerr << "Error! : myString::myString(const char* rhs) rhs is null." 
	    << endl;
	mystring_exit(1);	    
    }
    this->mLen  = strlen(rhs);
    this->mpStr = strnew(rhs);
}

inline myString::
myString(char c) 
{
    this->mLen = 1;
    char s[2];
    s[0] = c;
    s[1] = '\0';
    this->mpStr = strnew(s);
}

inline myString::
~myString() 
{ 
    delete [] this->mpStr;
#ifndef NDEBUG
    this->mpStr = NULL;
    this->mLen  = -1;
#endif
}

//------------------------------
// assignment
//------------------------------
inline myString& myString::
operator=(const myString& rhs)
{ 
    if(this != &rhs)
    {
	strdel(this->mpStr);
	this->mLen  = rhs.mLen;
	this->mpStr = strnew(rhs.mpStr);
    }
    return(*this);
}

inline myString& myString::
operator=(const char* rhs)
{
    if(rhs == NULL)
    {
	cerr << "Error! : myString::operator= get null." << endl;
	mystring_exit(1);
    }
    strdel(this->mpStr);    
    this->mLen  = strlen(rhs);
    this->mpStr = strnew(rhs);
    return(*this);    
}

inline myString& myString::
operator=(char c)
{
    strdel(this->mpStr);
    this->mLen = 1;
    char s[2];
    s[0] = c;
    s[1] = '\0';
    this->mpStr = strnew(s);
    return(*this);
}

//------------------------------
// cat operator versions
//------------------------------
inline myString& myString::
operator +=(const myString& rhs)
{
    const int newlength = this->mLen + rhs.mLen;
    char * pTmp = new char[newlength + 1];
    // strncpy は正に mLen しかコピーしない
    strncpy(pTmp, this->mpStr, this->mLen + 1);
    strncat(pTmp, rhs.mpStr,   rhs.mLen);
    
    strdel(this->mpStr);
    this->mpStr = strnew(pTmp);
    delete [] pTmp;
    pTmp = NULL;

    this->mLen = newlength + 1;
    
    return(*this);
}

//-----------------------------
// comparison operators
//-----------------------------
// inline int operator==(const myString& x, const myString& y) 
// {
//     return(strcmp(x.mpStr, y.mpStr) == 0);
// }
// 
// inline int operator!=(const myString& x, const myString& y)
// {
//     return(strcmp(x.mpStr, y.mpStr) != 0);
// }
// 
// inline int operator==(const myString& x, const char* t) 
// {
//     return(strcmp(x.mpStr, t) == 0);        
// }
// 
// inline int operator!=(const myString& x, const char* t) 
// {
//     return(strcmp(x.mpStr, t) != 0);        
// }
// 
// inline int operator==(const char* t, const myString& x) 
// {
//     return(strcmp(x.mpStr, t) == 0);        
// }
// 
// inline int operator!=(const char* t, const myString& x) 
// {
//     return(strcmp(x.mpStr, t) != 0);        
// }

#endif
