type extWstring extends wstring
	dim pPointerWstr as wstring ptr ' Pointer to the data
	dim iLen as Long ' Length line
	dim iSize as Long ' allocated bytes
	declare constructor()
	declare Constructor(byref as Const Wstring ptr)
	declare Constructor(byref as Const extWstring)
	declare Constructor(byref as Const string)		
	declare Constructor(as Long)
	declare Destructor()
	declare operator let(byref as Const wstring ptr)
	declare operator let(byREF as const extWstring)
	declare operator let(byREF as const string)
	Declare Operator &=(ByRef As Const wString ptr)
	Declare Operator &=(ByRef As Const String)
	Declare Operator &=(ByRef As const extWstring)
	Declare Operator &=(Byval As const Longint)
	Declare Operator &=(Byval As const DOUBLE)
	Declare Operator +=(ByRef As Const wString ptr)
	Declare Operator +=(ByRef As Const String)
	Declare Operator +=(ByRef As const extWstring)
	Declare Operator Cast() ByRef As Const wString
	Declare Operator [](as Long) ByRef As USHORT
	declare property UTF8() as string
	declare property UTF8(ByRef As const string)
	const SZW as Long = sizeof(wstring) ' size wstring (linux - 4 , windows - 2)
	Const SIZEALLOC As Long = 30*SZW
End Type

' init default
PRIVATE constructor extWstring()
	dim as long iSize = SIZEALLOC
	this.pPointerWstr = allocate( iSize )
	this.iLen = 0
	this.iSize = iSize
	if this.pPointerWstr then (this.pPointerWstr)[0] = 0
End Constructor

' init assign , let operators , &= operators
#macro MACRO_ASSIGN_LET_STRING(operations , macrotype , macrotypeSTR , flagConcatOrPlus , Specifier)
	#if operations = "ASSIGN"	
		#define	__BEGIN_MACROCLASS_BLOCK__ constructor extWstring
		#define	__END_MACROCLASS_BLOCK__ End Constructor
	#elseif operations = "LET"
		#undef __BEGIN_MACROCLASS_BLOCK__
		#undef __END_MACROCLASS_BLOCK__
		#define	__BEGIN_MACROCLASS_BLOCK__ Operator extWstring.Let
		#define	__END_MACROCLASS_BLOCK__ End Operator
	#elseif operations = "&="
		#undef __BEGIN_MACROCLASS_BLOCK__
		#define	__BEGIN_MACROCLASS_BLOCK__ Operator extWstring.&=
	#elseif operations = "+="
		#undef __BEGIN_MACROCLASS_BLOCK__
		#define	__BEGIN_MACROCLASS_BLOCK__ Operator extWstring.+=			
	#EndIf
	PRIVATE __BEGIN_MACROCLASS_BLOCK__(Specifier s as Const macrotype)
		#if macrotypeSTR = "WSTRING PTR"
			dim as Long iLen = len(*s)
		#elseif macrotypeSTR = "EXTWSTRING"
			dim as Long iLen = s.iLen
		#elseif macrotypeSTR = "STRING"
			dim as Long iLen = len(s)
		#elseif macrotypeSTR = "NUMERIC"
			#if flagConcatOrPlus = 1
				dim sz as Wstring*30 = wstr(s)
				dim as Long iLen = len(sz)
			#EndIf						
		#EndIf
		dim as Long iSize = iLen * SZW + SZW
		dim as Long iLenTemp = this.iLen
		#if flagConcatOrPlus = 1
			if this.iSize < this.iLen * SZW + iSize then
				iSize = this.iLen * SZW + iSize + SIZEALLOC
				this.pPointerWstr = reallocate(this.pPointerWstr , iSize)
				this.iSize = iSize
			EndIf
			this.iLen = iLen + this.iLen
		#else
			if iSize > this.iSize orelse (iSize + SIZEALLOC) < this.iSize then
				iSize +=SIZEALLOC
				if this.pPointerWstr then deallocate(this.pPointerWstr)
				this.pPointerWstr = allocate(iSize)
				this.iSize = iSize
			EndIf
			this.iLen = iLen		
		#endif
		dim as short ptr pDest , pSource 
		dim as BOOLEAN bFlagDeallocate
		#if macrotypeSTR = "WSTRING PTR"
			pSource = cast(short ptr,s)
		#elseif macrotypeSTR = "EXTWSTRING"
			pSource = cast(short ptr,s.pPointerWstr)
		#elseif macrotypeSTR = "STRING"
			dim as Long iBlen = iLen*SZW+SZW
			Dim As WString Ptr pwBuf
			pwBuf  = Allocate( iBlen )
			if pwBuf then
				MultiByteToWideChar(CP_ACP, 0, StrPtr(s) , -1, pwBuf, iBlen)
				pSource = cast(short ptr, pwBuf)
				bFlagDeallocate = TRUE
			endif
		#elseif macrotypeSTR = "NUMERIC"
			#if flagConcatOrPlus = 1		
				pSource = cast(short ptr, @sz)
			#EndIf
		#EndIf
		#if flagConcatOrPlus = 1
			pDest = cast(short ptr,this.pPointerWstr) + iLenTemp
		#else
			pDest = cast(short ptr,this.pPointerWstr)
		#EndIf
		if pDest andalso pSource then
			memcpy(pDest , pSource, iLen * SZW)
			cast(short ptr ,(this.pPointerWstr))[this.iLen] = 0
		EndIf
		if bFlagDeallocate then
			if pSource then deallocate(pSource)
		EndIf
	__END_MACROCLASS_BLOCK__	
#EndMacro

MACRO_ASSIGN_LET_STRING("ASSIGN" , Wstring ptr , "WSTRING PTR" , 0 , byref)
MACRO_ASSIGN_LET_STRING("ASSIGN" , extWstring , "EXTWSTRING" , 0 , byref)
MACRO_ASSIGN_LET_STRING("ASSIGN" , string , "STRING" , 0 , byref)
MACRO_ASSIGN_LET_STRING("LET" , Wstring ptr , "WSTRING PTR" , 0 , byref)
MACRO_ASSIGN_LET_STRING("LET" , extWstring , "EXTWSTRING" , 0 , byref)
MACRO_ASSIGN_LET_STRING("LET" , string , "STRING" , 0 , byref)
MACRO_ASSIGN_LET_STRING("&=" , Wstring ptr , "WSTRING PTR" , 1 , byref)
MACRO_ASSIGN_LET_STRING("&=" , extWstring , "EXTWSTRING" , 1 , byref)
MACRO_ASSIGN_LET_STRING("&=" , string , "STRING" , 1 , byref)
MACRO_ASSIGN_LET_STRING("&=" , longint , "NUMERIC" , 1 , byval)
MACRO_ASSIGN_LET_STRING("&=" , DOUBLE , "NUMERIC" , 1 , Byval)
MACRO_ASSIGN_LET_STRING("+=" , Wstring ptr , "WSTRING PTR" , 1 , byref)
MACRO_ASSIGN_LET_STRING("+=" , extWstring , "EXTWSTRING" , 1 , byref)
MACRO_ASSIGN_LET_STRING("+=" , string , "STRING" , 1 , byref)

' init fix size
PRIVATE Constructor extWstring(byval iNumberSimbols as long)
	this.iLen = iNumberSimbols * SZW
	this.iSize = this.iLen * SZW + SZW
	this.pPointerWstr = callocate(this.iSize)
End Constructor

PRIVATE Destructor extWstring()
	if pPointerWstr then
		deallocate(pPointerWstr)
		pPointerWstr = 0
	EndIf
End Destructor

PRIVATE Operator extWstring.Cast() ByRef As Const WString
	Return *(This.pPointerWstr)
End Operator

PRIVATE Operator extWstring.[](iIndex as Long) ByRef As USHORT
	Return (This.pPointerWstr)[iIndex]	
End Operator

PRIVATE Operator *(ByRef extWS As const extWstring) As const wString ptr
	return extWS.pPointerWstr
End Operator

PRIVATE operator len(w as extWstring) as integer
	return w.iLen
End Operator

PRIVATE property extWstring.UTF8() as string
	dim as Long iBlen 
	Dim As zString Ptr szBuf
	dim as string sRet
	iBlen = WideCharToMultiByte (CP_UTF8  , 0 , this.pPointerWstr , -1 , 0 , 0 , 0 , 0)
	szBuf  = CAllocate( iBlen + 1 )
	if szBuf then
		WideCharToMultiByte (CP_UTF8 , 0 , this.pPointerWstr , -1 , Cast( LPSTR ,szBuf) , iBlen , 0 , 0)
		sRet = *szBuf
		if szBuf then deallocate szBuf
	endif
	return sRet
End Property

PRIVATE property extWstring.UTF8(ByRef s As const string)
	dim as Long iLen = Len(s) , iSize
	dim as Long iBlen
	Dim As WString Ptr pwBuf
	
	iBlen = MultiByteToWideChar(CP_UTF8, 0, StrPtr(s) , -1, 0 , iBLen)
	
	if iBlen > 0 then
		pwBuf  = Allocate( iBlen*SZW + SZW)
		if pwBuf then
			iBlen = MultiByteToWideChar(CP_UTF8, 0, StrPtr(s) , -1, pwBuf, iBLen)
			if iBlen > 0 then
				iSize = iBlen*SZW+SZW
				If iSize > This.iSize Orelse (iSize + SIZEALLOC) < This.iSize Then
					this.iSize = iSize + SIZEALLOC
					if this.pPointerWstr then deallocate(this.pPointerWstr)
					this.pPointerWstr = allocate(this.iSize)
				EndIf
				This.iLen = iBlen - 1
				if this.pPointerWstr then
					memcpy( this.pPointerWstr , pwBuf , iBlen*SZW )
					cast(short ptr ,(this.pPointerWstr))[this.iLen] = 0
				endif
			endif
			if pwBuf then deallocate pwBuf
		endif
	endif
End Property

PRIVATE function val (w as extWstring) as double
	return val(**w)
End function

PRIVATE function valint (w as extWstring) as integer
	return valint(**w)
End function

PRIVATE function right (w as extWstring , n as integer) as extWstring
	dim sRet as extWstring
	sRet = right(**w ,  n )
	return sRet
End function

PRIVATE function left (w as extWstring , n as integer) as extWstring
	dim sRet as extWstring
	sRet = left(**w ,  n )
	return sRet	
End Function
