/*
 Copyright (C) 2010 Kuri-Applications

 UString.h - declarations of _StringW
 */

#ifndef __USTRING_H__
#define __USTRING_H__

typedef const BYTE FAR* LPCBYTE;

#ifndef __nullterminated
#define __nullterminated
#endif

#ifndef UNALIGNED
#define UNALIGNED
#endif

typedef __nullterminated WCHAR UNALIGNED *LPUWSTR, *PUWSTR;
typedef __nullterminated CONST WCHAR UNALIGNED *LPCUWSTR, *PCUWSTR;

/////////////////////////////////////////////////////////////////////////////
// _StringW - 文字列クラス (Unicode)

class _StringW
{
private:
	LPWSTR m_lpszData;
	LPSTR m_lpszLast;
	UINT m_uCodePage;

public:
	_StringW(wchar_t wch, DWORD nCount);
	_StringW(char ch, DWORD nCount, UINT uCodePage = CP_ACP);
	_StringW(const _StringW& _string);
	_StringW(LPCSTR lpszString, UINT uCodePage = CP_ACP);
	_StringW(LPCUWSTR lpszString);
	_StringW();
	~_StringW();

public:
	const _StringW& operator = (LPCUWSTR lpszString);
	const _StringW& operator = (LPCSTR lpszString);
	const _StringW& operator = (const _StringW& _string);

	_StringW operator + (LPCUWSTR lpszString) const;
	_StringW operator + (LPCSTR lpszString) const;
	_StringW operator + (const _StringW& _string) const;
	_StringW operator + (char ch) const;
	_StringW operator + (wchar_t ch) const;
	_StringW operator & (LPCUWSTR lpszString) const;
	_StringW operator & (LPCSTR lpszString) const;
	_StringW operator & (const _StringW& _string) const;
	_StringW operator & (char ch) const;
	_StringW operator & (wchar_t ch) const;
	const _StringW& operator += (LPCUWSTR lpszString);
	const _StringW& operator += (LPCSTR lpszString);
	const _StringW& operator += (const _StringW& _string);
	const _StringW& operator += (char ch);
	const _StringW& operator += (wchar_t ch);
	const _StringW& operator &= (LPCUWSTR lpszString);
	const _StringW& operator &= (LPCSTR lpszString);
	const _StringW& operator &= (const _StringW& _string);
	const _StringW& operator &= (char ch);
	const _StringW& operator &= (wchar_t ch);

	operator LPCWSTR() const;
	operator LPSTR();
	wchar_t operator [] (DWORD uIndex) const;
	wchar_t& operator [] (DWORD uIndex);

public:
	void Empty();
	DWORD GetLength() const;
	DWORD GetLengthA() const;
	BOOL IsEmpty() const;
	BOOL LoadString(UINT uID);
	BOOL WINAPIV Format(LPCSTR lpszString, ...);
	// no unaligned
	BOOL WINAPIV Format(LPCWSTR lpszString, ...);
	BOOL WINAPIV Format(const _StringW* pstrFormat, ...);
	BOOL WINAPIV Format(UINT uID, ...);
	int Compare(LPCSTR lpszString, bool bNoCase = false, DWORD uLength = 0xFFFFFFFF) const;
	// no unaligned
	int Compare(LPCWSTR lpszString, bool bNoCase = false, DWORD uLength = 0xFFFFFFFF) const;
	int Compare(const _StringW& strCompare, bool bNoCase = false) const;

	DWORD AppendChar(char ch);
	DWORD AppendChar(wchar_t wch);
	DWORD AppendString(LPCSTR lpszString, DWORD uLength = 0xFFFFFFFF);
	DWORD AppendString(LPCUWSTR lpszString, DWORD uLength = 0xFFFFFFFF);
	DWORD AppendString(const _StringW& strInsert);
	DWORD InsertChar(char ch, DWORD uPos);
	DWORD InsertChar(wchar_t wch, DWORD uPos);				// uPos は Unicode 文字列での位置
	DWORD InsertString(LPCSTR lpszString, DWORD uPos, DWORD uLength = 0xFFFFFFFF);
	DWORD InsertString(LPCUWSTR lpszString, DWORD uPos, DWORD uLength = 0xFFFFFFFF);	// uPos は Unicode 文字列での位置
	DWORD InsertString(const _StringW& strInsert, DWORD uPos);
	wchar_t DeleteChar(DWORD uPos);
	bool DeleteString(DWORD uStart, DWORD uLength);

	LPWSTR GetBuffer(DWORD uLength = 0);
	void ReleaseBuffer(DWORD uNewLength = 0xFFFFFFFF);
	LPSTR GetBufferA(DWORD uLength = 0);
	void ReleaseBufferA(BOOL bSetLength = TRUE, DWORD uNewLength = 0xFFFFFFFF);
	void SetString(LPCSTR lpszString, DWORD uLength = 0xFFFFFFFF);
	// lpszString can be the buffer which this _StringW owns
	void SetString(LPCUWSTR lpszString, DWORD uLength = 0xFFFFFFFF);
	void SetString(const _StringW& strData, DWORD uLength = 0xFFFFFFFF);

	LPSTR AllocAnsiString() const;

	UINT GetCodePage() const;
	void SetCodePage(UINT uCodePage);

public:
	//// these funtions are extentions for this application

	void SetUTF8String(LPCBYTE lpBuffer, DWORD dwByteLength);
	// not necessary to call free() (can't modify returned buffer)
	LPCBYTE AllocUTF8String(LPDWORD lpdwLength = NULL);
	//// need to call free()
	//LPBYTE AllocUTF8StringC(LPDWORD lpdwLength = NULL) const;
};

#endif // __USTRING_H__
