SOL9 2.0 Class: StringT

 SOL9 C++ Class Library  SOL9 Samples  SOL9 Tutorial  SOL9 FAQ  SOL9 ClassTree 

Source code

/*
 * StringT.h 
 * Copyright (c) 2012 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


// SOL9
// 2009/10/10
// 2012/03/07 Updated Constructor to allow a shallowCopy

#pragma once
#include <sol\Object.h>

#include <sol\OutOfMemoryException.h>
#include <sol\NullPointerException.h>
#include <sol\OutOfRangeException.h>
#include <sol\InvalidArgumentException.h>

namespace SOL {

template <class T> class StringT :public Object {

private:
    int        length;
    T*    text;
    
private:
    bool copy(const T* string)
    {
        bool rc = false;
        if (string != NULL) {
            int len = strlen(string);

            T* temp = new T[len+1];
            if(temp) {
                strcpy_s(temp, len+1, string);
                if(this->text != string && this->text !=NULL) {
                    //_soltrace("String::copy,1,delete text\n");
                    delete [] this->text;
                }
                this->text = temp;
                this->length = len;
                rc = true;
            } else {
                //Memory allocation error.
            }
        }
        return rc;
    }

public:
    /**
     */
    StringT()
        :length(0),
        text(NULL)
    {
        //_soltrace("String::String()\n");
    }

public:
    //2011/01/28
    StringT(T* array, int len)
    :length(0),
    text(NULL) 
    {     
        deepCopy(array, len);
    }

public:
 
    StringT(const T* string, bool deepCopy=true)
    :length(0),
    text(NULL) 
    {     
        if (string) {
            if (deepCopy) {
                if (copy(string) == false) {
                    throw OutOfMemoryException("String::String,1,Failed to create a string");
                }
            } else {
                shallowCopy((T*)string);
            }
        }
    }

// 1999.09.03 Added

public:
    StringT(const StringT* string)
    :length(0),
    text(NULL) 
    {     
        if (string) {
            const T*    str = string->getContents();
            if (str == NULL) {
                return;
            }
            else {
                if (copy(str) == false) {
                    throw OutOfMemoryException("String::String,2,Failed to create a string");
                }
            }
        }
    }


public:
    StringT(const StringT& string)
    :length(0),
    text(NULL)
    {
        //this->length = string.getLength();
        //this->text = NULL;
        const T* str = string.getContents();
        if (str == NULL) {
            return;
        } else {
            if (copy(str) == false) {
                throw OutOfMemoryException("Failed to create a string");
            }
        }
    }

public:
    ~StringT() { 
        clear();
    }

private:
    // 2009/04/09 Modiffied to call SecureZeroMemory
    void clear() { 
        if (this->text) {
            //2009/04/09
            SecureZeroMemory(this->text, this->length);
            delete [] this->text;
        }
        this->text =NULL;
        this->length = 0;
    }

public:
    // 2009/04/09 Call SecureZeroMemory() and  delete the memory area
    void secureClear() { 
        if (this->text) {
            SecureZeroMemory(this->text, this->length);
            delete [] this->text;
        }
        this->text =NULL;
        this->length = 0;
    }

public:
    T*   getContents() const { 
        return this->text; 
    }

public:
    int     getLength() const  { 
        return this->length; 
    }

public:
    //2009/04/10
    bool isEmpty() {
        bool rc = false;
        if (this->length>0 && this->text !=NULL) {
            rc = true;
        }
        return rc;
    }


public:
    operator T*() const{
        return this->text;
    }

public:
    operator const T*() const{
        return this->text;
    }

public:
    StringT& operator=(const T* string)
    { 
        _soltrace("String::operator=(const T*)\n");
        if (string != NULL) {
            if(copy(string) == false) {
                throw OutOfMemoryException("Failed to substitue a string");
            }
        }
        return *this;
    }

public:
    //2011/01/28
    // The string parameter can be non-NULL terminated.
    void deepCopy(T* string, int length)
    {
        if (string != NULL && length>0) {
            if (this->text != string) {
                clear();
            }
            int len = length;

            T* temp = new T[len+1];
            memcpy(temp, string, len);
            temp[len] = NULL;    //Put a NULL char at this len position to make a NULL terminated string
            this->text = temp;
            this->length = len;
        } else {
            clear();

            this->text   = NULL;
            this->length = 0;
        }
    }

public:
    void shallowCopy(T* string)
    { 
        // Accept a string of NULL
        _soltrace("String::shallowCopy(const T*)\n");
        if (string) {
            if (this->text != string) {
                clear();
            }
            this->text   = string;
            this->length = strlen(string);
        }
        else {
            clear();

            this->text   = string;    //NULL
            this->length = 0;
            //throw InvalidArgumentException("String::shallowCopy,InvalidArgument");
        }        
    }

public:
    StringT& operator=(const StringT& string)
    {        
        _soltrace("String::operator=(const String&)\n");

        //this->length = string.getLength();
        T* str = string.getContents();
        if (str) {
            if (copy(str) == false) {
                throw OutOfMemoryException("Failed to substitue a string");
            }
        } else {
            //str = NULL;
            clear();

            this->text = str;
            this->length = 0;
        }
        return *this;
    }

public:
    int operator==(const T* string)
    {
        int rc = 0;
        if (this->text == NULL && string ==NULL) {
            rc = 1;
        }

        //2008/07/08
        if (this->text != NULL && string != NULL) {
            if(strcmp(this->text, string) == 0) {
                rc = 1;
            }
        }
        return rc;
    }


    //int operator==(String& string)
public:
    int operator==(StringT& string)
    {
        int rc = 0;
        const T* str = (const T*)string;
        if (this->text == NULL && str ==NULL) {
            rc = 1;
        }

        if (this->text != NULL && str != NULL) {
            if(strcmp(this->text, str) == 0) {
                rc = 1;
            }
        }
        return rc;
    }

public:
    StringT& operator+(const T* string)
    {
        if(string == NULL) {
            return *this;
        }
        size_t orglen = this->length;
        this->length += strlen(string);
        T* temp = new T[this->length+1];
        memset(temp, (T)0, length+1);
        memcpy(temp, this->text, orglen);
        memcpy(temp+orglen, string, strlen(string));

        if(this->text != string) {
            delete [] text;
        }
        text = temp;
        return *this;
    }



public:
    int compare(Object* object)
    {
        int rc = 0;
        if (object==NULL) {
            return rc;
        }

        StringT* string = (StringT*)object;
        const T* p1 = this->text;

        const T* p2 = (const T*)(*string);
        if (p1 == NULL && p2 == NULL) {
            rc = 1;
        }
        if (p1 != NULL && p2 != NULL) {
            rc = strcmp(p1, p2);
        }
        return rc;
    }


public:
    const T* find(const T* string)    
    {
        const T* ptr = NULL;
        if (this->text && string) {
            ptr = strstr(this->text, string);
        }
        return ptr;
    }


public:
    int replace(T oc, T nc)
    {
        int    n = 0;
        if (this->text) {
            for (int i = 0; i<this->length; i++) {
                if (text[i] == oc) {
                    text[i] = nc;
                    n++;
                }
            }
        }
        return n;
    }

//<added date="2000/11/10">
public:
    StringT& operator+(T ch)
    {
        T string[2];
        string[0] = ch;
        string[1] = (T)0;//Zero;

        return StringT::operator+(string);
    }

private:
    StringT& appendFormat(T* format,...)
    {
        T buffer[128];
        memset(buffer, (T)0, 128);

        va_list pos;
        va_start(pos, format);
        vsprintf(buffer, format, pos);
        va_end(pos);
        return StringT::operator+(buffer);
    }

public:
    StringT& operator+(int num)
    {
        T format[3] ={(T)'%',(T)'d', (T)0};    
        return appendFormat(format, num);
    }


public:
    StringT& operator+(float num)
    {
        T format[3] ={(T)'%',(T)'f', (T)0};    
        return appendFormat(format, num);

    }

public:
    StringT& operator+(double num)
    {
        T format[3] ={(T)'%',(T)'f', (T)0};    
        return appendFormat(format, num);
    }


public:
    bool equals(const T* str) {
        bool rc = false;
        if(this->text != NULL && str != NULL) {
            if(strcmp(this->text, str) == 0) {
                   rc = true;
            }
        }
        return rc;
    }

public:
    bool equals(const StringT& str) {
        return equals((const T*)str);
    }

public:
    bool equalsIgnoreCase(const T* str) {
        bool rc = false;

        if(this->text != NULL && str != NULL) {
            //strcmpi -> stricmp
            if(_stricmp(this->text, str) == 0) {
                   rc = true;
            }
        }
        return rc;
    }

public:
    bool equalsIgnoreCase(const StringT& str) {
        return equalsIgnoreCase((const T*)str);
    }


public:
    void trim()
    {
        T* rt = StringT::trim(this->text);

        if (rt) {
            clear();
            //Shallow copy
            this->text = rt;
            this->length = strlen(rt);
        }
    }

public:
    void trimOnNewLine() {
        if (this->text) {
            T newLine[2] = {(T)'\r', (T)'\n'};

            T* ptr = (T*)strstr(this->text, newLine);
            if (ptr) {
                //Terminate this text on this ptr position by putting '\0';
                *ptr = '\0';
                this->length = strlen(this->text);
            }
        }
    }


public:
    /**
     */    
    bool     startsWith(const T* start) {
        return StringT::startsWith(this->text, start);
    }

public:
    /**
     */    
    bool     startsWithIgnoreCase(const T* start) {
        return StringT::startsWithIgnoreCase(this->text, start);
    }

public:
    /**
     */    
    bool     endsWith(const T* end) {
        return StringT::endsWith(this->text, end);
    }

public:
    /**
     */    
    bool     endsWithIgnoreCase(const T* end) {
        return StringT::endsWithIgnoreCase(this->text, end);
    }

public:
    //2009/11/12
    const T* findLast(const T* string)
    {
        return StringT::findLast(this->text, string);
    }

public:
    //2009/11/12
    static const T* findLast(const T* text, const T* string)
    {
        const T* ptr = NULL;

        if (text && string) {
            int tlen = strlen(text);
            int slen = strlen(string);
            if (tlen < slen) {
                return ptr;
            } else {
                for(int i = tlen - slen; i>=0; i--) {
                    int n= strncmp(text + i, string, slen);
                    if (n == 0) {
                        ptr = text + i;
                        break;
                    }
                }
            }    
        }
        return ptr;
    }

public:
    //2009/11/12
    const T* findFirst(const T* string) {
        return StringT::findFirst(this->text, string);        
    }

public:
    //2009/11/12
    static const T* findFirst(const T* text, const T* string) {
        const T* ptr = NULL;
        if (text && string) {
            ptr = strstr(text, string);
        }
        return ptr;
    }


public:
    T&    operator[](int n) 
    {
        if (this->text == NULL) {
            throw NullPointerException("String::operator[] - Text is NULL");
        }
        if (n <=0 || n>this->length) {
            throw OutOfRangeException("String::operator[] - Index is out of range");
        }
        
        //
        return text[n]; 
    }


//////////////////////////////////////////////////////////////////////
///
public:
    static T* trim(T* string) {
        if (string == NULL) {
            return string;
        }
        
        size_t slen = strlen(string)+1;

        T* temp = new T[slen];
        strcpy_s(temp, slen, string);
        T* p = temp;

        while (*p == (T)' ' || *p == (T)'\t' || *p ==(T)'\r' || *p==(T)'\n') {
            p++;
        }

        T* t = p + strlen(p) -1;
        while (*t == (T)' ' || *t == (T)'\t' || *t ==(T)'\r' || *t==(T)'\n') {
            if (p == t) break;
            *t = (T)'\0';
            t--;
        }

        size_t plen = strlen(p)+1;
        T* rt = new T[plen];
        strcpy_s(rt, plen, p);

        delete [] temp;

        return rt;
    }



public:
    /**
     * 
     * @param string    
     * @param start
     * @return bool
     *
     */    
    static bool  startsWith(const T* string, const T* start) {
        bool rc = false;
        if (string != NULL && start != NULL) {
            if (strncmp(string, start, strlen(start)) ==0) {
                rc = true;
            }
        }
        return rc;
    }

public:
    /**
     * 
     * @param string
     * @param start
     * @return bool
     */    
    static bool  startsWithIgnoreCase(const T* string, const T* start) {
        bool rc = false;
        if (string != NULL && start != NULL) {
    
            if (_strnicmp(string, start, strlen(start)) ==0) {
                rc = true;
            }
        }
        return rc;
    }


public:
    /**
     * 
     * @param string
     * @param end
     * @return bool
     */    

    static bool endsWith(const T* string, const T* end) {
        bool rc = false;
        if (string != NULL && end != NULL) {
            size_t tlen = strlen(string);
            size_t slen = strlen(end);
            if (tlen >= slen) {
                if (strncmp(string+tlen-slen, end, slen) ==0) {
                    rc = true;
                }
            }
        }
        return rc;
    }

public:
    /**
     * 
     * @param string
     * @param end    
     * @return bool
     */    
    static bool endsWithIgnoreCase(const T* string, const T* end) {
        bool rc = false;
        if (string != NULL && end != NULL) {
            size_t tlen = strlen(string);
            size_t slen = strlen(end);
            if (tlen >= slen) {
                if (_strnicmp(string+tlen-slen, end, slen) ==0) {
                    rc = true;
                }
            }
        }
        return rc;
    }

};

}


Last modified: 1 Apr 2012

Copyright (c) 2009-2012 Antillia.com ALL RIGHTS RESERVED.