#pragma option push -b -a8 -pc -A- /*P_O_Push*/
//***************************************************************************
//
//  Copyright (c) 1997-1999 Microsoft Corporation
//
//  CHSTRING.h
//
//  Purpose: Utility library version of MFC CString
//
//***************************************************************************

#if _MSC_VER > 1000
#pragma once
#endif

#ifndef _CHSTRING_H
#define _CHSTRING_H

/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <limits.h>
#include <tchar.h>
#include <polarity.h>
#pragma warning( disable : 4290 ) // Ignore 'C++ Exception Specification ignored'
#include <ProvExce.h>

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

struct _DOUBLE  { BYTE doubleBits[sizeof(double)]; };

void POLARITY WINAPI SetCHStringResourceHandle(HINSTANCE handle);

/////////////////////////////////////////////////////////////////////////////
// CHString formatting
/////////////////////////////////////////////////////////////////////////////
#define TCHAR_ARG   WCHAR
#define WCHAR_ARG   WCHAR
#define CHAR_ARG    char

#if defined(_68K_) || defined(_X86_)
	#define DOUBLE_ARG  _DOUBLE
#else
	#define DOUBLE_ARG  double
#endif

struct CHStringData
{
    long nRefs;
	int nDataLength;
	int nAllocLength;

	WCHAR* data()
	{
		return (WCHAR*)(this+1); 
	}
};

/////////////////////////////////////////////////////////////////////////////
class POLARITY CHString
{
    protected:

    	LPWSTR m_pchData;               // pointer to ref counted string data

    protected:

                        	            // implementation helpers

        CHStringData* GetData() const;  // returns data pointer
	    void Init();
	    void AllocCopy(CHString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const throw ( CHeap_Exception ) ;
        void AllocBuffer(int nLen) throw ( CHeap_Exception ) ;
	    void AssignCopy(int nSrcLen, LPCWSTR lpszSrcData) throw ( CHeap_Exception ) ;
	    void ConcatCopy(int nSrc1Len, LPCWSTR lpszSrc1Data, int nSrc2Len, LPCWSTR lpszSrc2Data) throw ( CHeap_Exception ) ;
        void ConcatInPlace(int nSrcLen, LPCWSTR lpszSrcData);
	    void CopyBeforeWrite() throw ( CHeap_Exception ) ;
	    void AllocBeforeWrite(int nLen) throw ( CHeap_Exception ) ;
	    void Release();
	    static void WINAPI Release(CHStringData* pData);
        static inline int WINAPI SafeStrlen(LPCWSTR lpsz)	{ return (lpsz == NULL) ? 0 : wcslen(lpsz); }

        // Helper function used to load resource into lpszBuf buffer.
        int LoadStringW(UINT nID, LPWSTR lpszBuf, UINT nMaxBuf) throw ( CHeap_Exception ) ;

    public:

// Constructors/Destruction

        CHString();
        CHString(const CHString& stringSrc);
        CHString(WCHAR ch, int nRepeat = 1) throw ( CHeap_Exception ) ;
        CHString(LPCSTR lpsz) throw ( CHeap_Exception ) ;
        CHString(LPCWSTR lpsz) throw ( CHeap_Exception ) ;
        CHString(LPCWSTR lpch, int nLength) throw ( CHeap_Exception ) ;
        inline CHString(const unsigned char* lpsz)	{ Init(); *this = (LPCSTR)lpsz; }

        ~CHString();

// Functions

        void SetAt(int nIndex, WCHAR ch) throw ( CHeap_Exception ) ;
        void Empty();    

        // inlines

	    inline int GetLength() const { return GetData()->nDataLength; }
        inline BOOL IsEmpty() const  { return GetData()->nDataLength == 0; }

#if (!defined DEBUG && !defined _DEBUG)
        inline WCHAR GetAt(int nIndex) const{ return m_pchData[nIndex]; }
        inline WCHAR operator[](int nIndex) const{	return m_pchData[nIndex]; }
#else
        WCHAR GetAt(int nIndex) const;
        WCHAR operator[](int nIndex) const;
#endif
        inline operator LPCWSTR() const 	{ return m_pchData; }
        inline int GetAllocLength() const	    { return GetData()->nAllocLength; }

// overloaded assignment

        const CHString& operator=(const CHString& stringSrc) throw ( CHeap_Exception ) ;
        const CHString& operator=(WCHAR ch) throw ( CHeap_Exception ) ;
        const CHString& operator=(LPCSTR lpsz) throw ( CHeap_Exception ) ;
	    const CHString& operator=(LPCWSTR lpsz) throw ( CHeap_Exception ) ;
        inline const CHString& operator=(const unsigned char* lpsz) throw ( CHeap_Exception ) { *this = (LPCSTR)lpsz; return *this; }
        inline const CHString& operator=(CHString *p) throw ( CHeap_Exception ) { *this = *p; return *this; }
        inline const CHString& operator=(char ch) throw ( CHeap_Exception ) { *this = (WCHAR)ch; return *this; }        
        
        inline const CHString& CHString::operator+=(char ch) throw ( CHeap_Exception ) { *this += (WCHAR)ch; return *this; }
        friend inline CHString  operator+(const CHString& string, char ch) throw ( CHeap_Exception ) { return string + (WCHAR)ch; }
        friend inline CHString  operator+(char ch, const CHString& string) throw ( CHeap_Exception ) { return (WCHAR)ch + string; }

        const CHString& operator+=(const CHString& string) throw ( CHeap_Exception ) ;
        const CHString& operator+=(WCHAR ch) throw ( CHeap_Exception ) ;
	    const CHString& operator+=(LPCWSTR lpsz) throw ( CHeap_Exception ) ;

	    friend CHString POLARITY WINAPI operator+(const CHString& string1,  const CHString& string2) throw ( CHeap_Exception ) ;
	    friend CHString POLARITY WINAPI operator+(const CHString& string, WCHAR ch) throw ( CHeap_Exception ) ;
	    friend CHString POLARITY WINAPI operator+(WCHAR ch, const CHString& string) throw ( CHeap_Exception ) ;
	    friend CHString POLARITY WINAPI operator+(const CHString& string, LPCWSTR lpsz) throw ( CHeap_Exception ) ;
	    friend CHString POLARITY WINAPI operator+(LPCWSTR lpsz, const CHString& string) throw ( CHeap_Exception ) ;

// string comparison

	    int Compare(LPCWSTR lpsz) const;

	    inline int CompareNoCase(LPCWSTR lpsz) const
		{
			// ignore case

			return _wcsicmp(m_pchData, lpsz); 

		}   // MBCS/Unicode aware

	    inline int Collate(LPCWSTR lpsz) const
		{  
			// NLS aware
            // CHString::Collate is often slower than Compare but is MBSC/Unicode
            // aware as well as locale-sensitive with respect to sort order.

			return wcscoll(m_pchData, lpsz); 

		}   // locale sensitive

// Load string from resource file.

        BOOL LoadStringW(UINT nID) throw ( CHeap_Exception ) ;

// Access to string implementation buffer as "C" character array

	    LPWSTR GetBuffer(int nMinBufLength) throw ( CHeap_Exception ) ;
	    void ReleaseBuffer(int nNewLength = -1) throw ( CHeap_Exception ) ;
	    LPWSTR GetBufferSetLength(int nNewLength) throw ( CHeap_Exception ) ;
	    void FreeExtra() throw ( CHeap_Exception ) ;

// Use LockBuffer/UnlockBuffer to turn refcounting off

        LPWSTR LockBuffer() ;
        void UnlockBuffer();

// searching (return starting index, or -1 if not found)
// look for a single character match

        int Find(WCHAR ch) const;               // like "C" strchr
        int FindOneOf(LPCWSTR lpszCharSet) const;
        int ReverseFind(WCHAR ch) const;

// look for a specific sub-string

        int Find(LPCWSTR lpszSub) const;        // like "C" strstr

// upper/lower/reverse conversion

        void MakeUpper() throw ( CHeap_Exception ) ;
        void MakeLower() throw ( CHeap_Exception ) ;
        void MakeReverse() throw ( CHeap_Exception ) ;

// simple sub-string extraction

        CHString Mid(int nFirst, int nCount) const throw ( CHeap_Exception ) ;
        CHString Mid(int nFirst) const throw ( CHeap_Exception ) ;
        CHString Left(int nCount) const throw ( CHeap_Exception ) ;
        CHString Right(int nCount) const throw ( CHeap_Exception ) ;

        CHString SpanIncluding(LPCWSTR lpszCharSet) const throw ( CHeap_Exception ) ;
        CHString SpanExcluding(LPCWSTR lpszCharSet) const throw ( CHeap_Exception ) ;

// trimming whitespace (either side)

        void TrimRight() throw ( CHeap_Exception ) ;
        void TrimLeft() throw ( CHeap_Exception ) ;
    
// printf-like formatting using passed string
	    void __cdecl Format(LPCWSTR lpszFormat, ...) throw ( CHeap_Exception ) ;
	    void FormatV(LPCWSTR lpszFormat, va_list argList);

// printf-like formatting using referenced string resource
	    void __cdecl Format(UINT nFormatID, ...) throw ( CHeap_Exception ) ;

// format using FormatMessage API on passed string
    	// Warning: if you pass string inserts to this function, they must
        // be LPCSTRs on Win9x and LPCWSTRs on NT.
        void __cdecl FormatMessageW(LPCWSTR lpszFormat, ...) throw ( CHeap_Exception ) ;

// format using FormatMessage API on referenced string resource
    	// Warning: if you pass string inserts to this function, they must
        // be LPCSTRs on Win9x and LPCWSTRs on NT.
	    void __cdecl FormatMessageW(UINT nFormatID, ...) throw ( CHeap_Exception ) ;


#ifndef _NO_BSTR_SUPPORT

	    // OLE BSTR support (use for OLE automation)

	    BSTR AllocSysString() const throw ( CHeap_Exception ) ;
#endif

};

inline BOOL operator==(const CHString& s1, const CHString& s2)  { return s1.Compare(s2) == 0; }
inline BOOL operator==(const CHString& s1, LPCWSTR s2)      	{ return s1.Compare(s2) == 0; }

inline BOOL operator!=(const CHString& s1, const CHString& s2)	{ return s1.Compare(s2) != 0; }
inline BOOL operator!=(const CHString& s1, LPCWSTR s2)      	{ return s1.Compare(s2) != 0; }

inline BOOL operator<(const CHString& s1, const CHString& s2)   { return s1.Compare(s2) < 0; }
inline BOOL operator<(const CHString& s1, LPCWSTR s2)       	{ return s1.Compare(s2) < 0; }

inline BOOL operator>(const CHString& s1, const CHString& s2)	{ return s1.Compare(s2) > 0; }
inline BOOL operator>(const CHString& s1, LPCWSTR s2)       	{ return s1.Compare(s2) > 0; }

inline BOOL operator<=(const CHString& s1, const CHString& s2)	{ return s1.Compare(s2) <= 0; }
inline BOOL operator<=(const CHString& s1, LPCWSTR s2)      	{ return s1.Compare(s2) <= 0; }

inline BOOL operator>=(const CHString& s1, const CHString& s2)	{ return s1.Compare(s2) >= 0; }
inline BOOL operator>=(const CHString& s1, LPCWSTR s2)      	{ return s1.Compare(s2) >= 0; }

#endif
#pragma option pop /*P_O_Pop*/
