// ============================================================================
// = LIBRARY
// = FILENAME  otstr.h
// = AUTHOR    Shen beide
// = MODIFY    2006-02
// ====================================================================
#ifndef _OTSTRING_H
#define _OTSTRING_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>

#include "PubHeader.h"

typedef const char *LPCSTR;
typedef LPCSTR      LPCTSTR;

//////////////////////////////////////////////
#ifdef _DLL_PROJECT
class CLASS_EXPORT OTSTR
#else
class OTSTR
#endif
{
public:
    enum { INITIAL_SIZE=200 };

public:
    OTSTR(void);
    OTSTR(const OTSTR& str);
	OTSTR(OTSTR* pstr);
    OTSTR(char *buffer, int length=-1);

   ~OTSTR(void);

    bool  initsize(int size=INITIAL_SIZE, bool bisTrueContent=false);   // if (bisTrueContent) OTSTR:m_length=size
    void  setGrowsize(int growsize);
    
    int   GetLength(void) ;			//get the true length of buffer
    char* GetBuffer(int n=0) ;      //get the octstr buffer
    bool  isEmpty();
        
    void  set(char *buffer, int length=-1);
    void  set(char *buffer, int length, bool bTrimLeftAndRight);
    void  set(const char*buffer);

    void  Empty();

    char  getAt(int nIndex);
    bool  getAt(int nIndex,char& retchar);
    bool  setAt(int nIndex,char  newchar);
    
    void  ReplaceChar  (char  oldchar, char  newchar);
    bool  ReplaceString(char* oldstr , char* newstr );
    
    //////////////////////////////////////////////////////////
    bool  append (char  ch,   int num= 1);      // Append the string, auto realloc when data overflow  
    bool  append (char *data, int len=-1);      // Append the string, auto realloc when data overflow  
    bool  append (OTSTR& str);      
    bool  appends(const char* pszFormat, ...);
    
    bool  equal(char  *str, bool bcase=true);
    bool  equal(char  *str, int  length, bool bcase=true);
    bool  equal(OTSTR& str, bool bcase=true);
    
    OTSTR& Format (const char* pszFormat, ...);
    OTSTR& Format_(const char* pszFormat, va_list argptr); 
    
    OTSTR& operator += (OTSTR& s);
    OTSTR& operator += (char* s);
    void   operator=(const OTSTR& right);
    void   operator=(char* sright);
    friend bool  operator==(const OTSTR& left, const OTSTR& right);
    friend bool  operator==(const OTSTR& left, const char* sright);
    friend OTSTR operator+ (const OTSTR& left, const OTSTR& right);
    operator char*();       //  operator const char*();
    
    ////////////////////////////////////////////////////////
    // Search the char in the otstr buffer from the position startpos,
    // Return the position the char in the octstr buffer , -1 if not found . 
    int  Find(char ch, int startpos=0);
    int  ReverseFind(char ch, int startpos=-1);         // -1 mean from tail

    int  FindOneOf(char* szCharSet, int startpos=0);    // if (szCharSet==NULL) -> Find first visiable Char

    // Search the str in the otstr buffer from the postion startpos.  szFindlen=-1 mean strlen(lpszFind)
    // Return the start position of the str , -1 if not found 
	int  Find(const char* lpszFind, const int szFindlen, int nStart);

    ////////////////////////////////////////////////////////
    void toUpper(int startpos=0, int length=-1);
    void toLower(int startpos=0, int length=-1);

    OTSTR& TrimLeft (bool bOnlyWhiteSpace=true);
    OTSTR& TrimRight(bool bOnlyWhiteSpace=true);
    void   DeflateRight(int DeflateLen);
    
    OTSTR  Left (int nLen);
    OTSTR  Right(int nLen);
    OTSTR  Mid  (int nFirst, int nCount);
    
    OTSTR  LeftOf(char  separatorCh, bool bNotFoundRetNull=false);
    OTSTR  LeftOf(char* lpseparator, bool bNotFoundRetNull=false);

    ////////////////////////////////////////////////////////
    bool as_int2  (INT2&   Val,  int base=10);
    bool as_uint2 (UINT2&  uVal, int base=10);
    bool as_int4  (INT4&   lVal, int base=10);
    bool as_uint4 (UINT4&  ulVal,int base=10);
    bool as_double(double& dbVal);

    /////////////////////////////////////////////////////////////////////
    // Search string between the first CharLeft & matched CharRight,
    // The Level Check is Enabled, 
    // Return: the position the CharLeft in the octstr buffer, -1 if error or not found . 
    //         Sample:  str="a+(b+(c+2))+c";
    //                  str.Find_PairChars('(',')',0,true,strRet);
    //                  strRet is "b+(c+2)"
    // Used for Expression Analysis such as '(',')' and '['']' in C++
    int  Find_PairChars(char CharLeft, char CharRight, int startpos, bool bReturnBetween, OTSTR& strRet);
    int  Find_SkipPairChars(char ch,char* szCharLeft, char* szCharRight, int startpos); // 越过CharLeft-CharRight中的内容

    // 如果搜索中虽然字符等于CharLeft,CharRight,但前面有\\, 则该字符被转义,不算做CharLeft和CharRight, 需要跳过
    int  Find_PairChars(char CharLeft, bool bLeftEscapeEnabled,char CharRight, bool bRightEscapeEnabled, int startpos, bool bReturnBetween, OTSTR& strRet);
    
	/////////////////////////////////////////////////////////////////////
	//功  能：在lpszSour中查找字符串lpszFind，lpszFind中可以包含通配字符‘?’
	//参  数：nStart为在lpszSour中的起始查找位置
	//返回值：成功返回匹配位置，否则返回-1
    static int  Find(const char* lpszSour, const int szSourlen, const char* lpszFind, const int szFindlen, int nStart=0);

protected:
    char* m_buf;
    int   m_length; 			//the true length of buffer, string or byte sequence
    int   m_alloc_length;	 	//the allcation memory length
    int   m_growsize;
    
    void  OnCreate();
    void  OnDestroy();

    void  release();

    bool  ReallocBuffer(int newsize);
        
    static bool IsValidChar(unsigned char nChar,UINT2 MaskType);

    virtual char* malloc_(long  size);  
    virtual void  free_  (char* pbuffer);
    virtual char* realloc_(char *pOldbuffer, long newsize);

    static char NullOctstr[1];
};

///////////////////////////////////////////////

#endif /* _OTSTRING_H */
