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 Ulong
	Declare Property UTF8() As String
	Declare Property UTF8(Byref As Const String)
	Declare Function EncodeUTF8ToUnicode(sTextUtf8 As Const String) As Wstring Ptr
	Declare Function EncodeUnicodeToUTF8(wsText As Wstring Ptr) As String
	Declare Function CalculateUTF8ToUnicode(sTextUtf8 As Const String) As Long
	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 )
	if This.pPointerWstr then
		This.iLen = 0
		This.iSize = iSize
		(This.pPointerWstr)[0] = 0
	else
		print "Allocated memory error in Constructor extWstring!"
	endif
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 = CalculateUTF8ToUnicode(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)
			if This.pPointerWstr = 0 then
				print "Allocated memory error in MACRO_ASSIGN_LET_STRING!"
			EndIf			
			This.iSize = iSize
		Endif
	#else
		If iSize > This.iSize Orelse (iSize + SIZEALLOC) < This.iSize Then
			iSize += SIZEALLOC
			if This.pPointerWstr then Deallocate(This.pPointerWstr)
			This.pPointerWstr = Allocate(iSize)
			if This.pPointerWstr = 0 then
				print "Allocated memory error in MACRO_ASSIGN_LET_STRING!"
			EndIf
			This.iSize = iSize
		Endif		
	#endif
	Dim As Long Ptr pDest , pSource 
	Dim As Boolean bFlagDeallocate
	#if macrotypeSTR = "WSTRING PTR"
		pSource = Cast(Long Ptr,s)
	#elseif macrotypeSTR = "EXTWSTRING"
		pSource = Cast(Long Ptr,s.pPointerWstr)
	#elseif macrotypeSTR = "STRING"
		Dim As Wstring Ptr pwBuf
		pwBuf  = EncodeUTF8ToUnicode(s)
		iLen = Len(*pwBuf)
		pSource = Cast(Long Ptr, pwBuf)
		bFlagDeallocate = True
	#elseif macrotypeSTR = "NUMERIC"
		#if flagConcatOrPlus = 1
			pSource = Cast(Long Ptr, @sz)
		#endif
	#endif
	#if flagConcatOrPlus = 1
		This.iLen = iLen + This.iLen
		pDest = Cast(Long Ptr,This.pPointerWstr) + iLenTemp
	#else
		This.iLen = iLen
		pDest = Cast(Long Ptr,This.pPointerWstr)
	#endif
	If pDest Andalso pSource Then
		memcpy(pDest , pSource, iLen * SZW)
		Cast(Long 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)
	if This.pPointerWstr = 0 then
		print "Allocated memory error in Constructor extWstring!"
	EndIf
End Constructor

Private Destructor extWstring()
	if pPointerWstr then Deallocate(pPointerWstr)
End Destructor

Private Operator extWstring.Cast() Byref As Const Wstring
	Return *(This.pPointerWstr)
End Operator

Private Operator extWstring.[](iIndex As Long) Byref As Ulong
	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
	Return EncodeUnicodeToUTF8(This.pPointerWstr)
End Property

Private Property extWstring.UTF8(Byref s As Const String)
	Dim As Long iLen = Len(s) , iSize
	Dim As Wstring Ptr pwBuf
	If iLen > 0 Then
		pwBuf = EncodeUTF8ToUnicode(s)
		If pwBuf Then
			This.iLen = Len(*pwBuf)
			iSize = This.iLen*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)
				if This.pPointerWstr = 0 then
					print "Allocated memory error in extWstring.UTF8!"
					Exit Property
				EndIf
			Endif
			memcpy( This.pPointerWstr , pwBuf , iSize )
			Cast(Long Ptr ,(This.pPointerWstr))[This.iLen] = 0
		Endif
	Endif
	If pwBuf Then Deallocate pwBuf 
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

Private Function extWstring.CalculateUTF8ToUnicode(sTextUtf8 As Const String) As Long
	Dim As Long iIndex
	For i As Long = 0 To Len(sTextUtf8) -1
		If (sTextUtf8[i] And &hF8)  = &hf0 Andalso (sTextUtf8[i+1] And &hC0) = &h80 Andalso (sTextUtf8[i+2] And &hC0) = &h80 Andalso (sTextUtf8[i+3] And &hC0) = &h80 Then
			i+=3
		elseIf (sTextUtf8[i] And &hF0)  = &hE0 Andalso (sTextUtf8[i+1] And &hC0) = &h80 Andalso (sTextUtf8[i+2] And &hC0) = &h80 Then
			i+=2
		Elseif (sTextUtf8[i] And &hC0)  = &hC0 Andalso (sTextUtf8[i+1] And &hC0) = &h80 Then
			i+=1
		Endif
		iIndex+=1
	Next
	Return iIndex
End Function

Private Function extWstring.EncodeUTF8ToUnicode(sTextUtf8 As Const String) As Wstring Ptr
	Dim As Long iIndex
	Dim As Long shUnicodeSymbol
	Dim As Wstring Ptr ws = Callocate(Len(sTextUtf8)*4+4)
	if ws then
		For i As Long = 0 To Len(sTextUtf8) -1
			If (sTextUtf8[i] And &hF8)  = &hf0 Andalso (sTextUtf8[i+1] And &hC0) = &h80 Andalso (sTextUtf8[i+2] And &hC0) = &h80 Andalso (sTextUtf8[i+3] And &hC0) = &h80 Then
				shUnicodeSymbol = ((sTextUtf8[i] And &h7) Shl 18) Or ((sTextUtf8[i+1] And &h3F) Shl 12) Or (((sTextUtf8[i+2] And &h3F) Shl 6) Or (sTextUtf8[i+3] And &h3F))
				#ifdef __FB_WIN32__
					dim as Long iFirstSG = (((shUnicodeSymbol - &h10000) and &hFFC00) shr 10) + &hD800
					dim as Long iSecondSG = ((shUnicodeSymbol - &h10000) and &h3FF)+&hDC00
					(*ws)[iIndex] = iFirstSG
					(*ws)[iIndex+1] = iSecondSG
					iIndex+=2
					i+=3
					continue for
				#else
					i+=3
				#EndIf
			elseIf (sTextUtf8[i] And &hF0)  = &hE0 Andalso (sTextUtf8[i+1] And &hC0) = &h80 Andalso (sTextUtf8[i+2] And &hC0) = &h80 Then
				shUnicodeSymbol = ((sTextUtf8[i] And &hF) Shl 12) Or (((sTextUtf8[i+1] And &h3F) Shl 6) Or (sTextUtf8[i+2] And &h3F))
				i+=2
			Elseif (sTextUtf8[i] And &hC0)  = &hC0 Andalso (sTextUtf8[i+1] And &hC0) = &h80 Then
				shUnicodeSymbol = ((sTextUtf8[i] And &h1F) Shl 6) Or ((sTextUtf8[i+1] And &h3F))
				i+=1			
			Elseif (sTextUtf8[i] And &h80)  = &h0 Then
				shUnicodeSymbol = sTextUtf8[i]
			Else
				shUnicodeSymbol = &hFFFD
			Endif
			(*ws)[iIndex] = shUnicodeSymbol
			iIndex+=1
		Next
		(*ws)[iIndex] = 0
	else
		print "Allocated memory error in extWstring.EncodeUTF8ToUnicode!"
	endif
	Return ws
End Function

Private Function extWstring.EncodeUnicodeToUTF8(wsText As Wstring Ptr ) As String
	if wsText then
		Dim As Long iSimbol , iIndex , iLen = Len(*wsText)
		Dim As Byte Ptr psz = Allocate(iLen*4+1)
		if psz then
			For i As Long = 0 To iLen-1
				iSimbol = wsText[i]
				If iSimbol < &h80 Then
					psz[iIndex] = iSimbol
					iIndex+=1
				Elseif iSimbol < &h800 Then
					psz[iIndex] = &hC0 Or (iSimbol Shr 6)
					psz[iIndex+1] = &h80 Or (iSimbol And &h3f)
					iIndex+=2
				Elseif iSimbol < &h10000 Then
					if iSimbol < &hD800 Orelse iSimbol > &hDFFF then
						psz[iIndex] = (&he0 Or (&hF And (iSimbol Shr 12)))
						psz[iIndex+1] = &h80 Or (&h3f And (iSimbol Shr 6))
						psz[iIndex+2] = &h80 Or (iSimbol And &h3F)
						iIndex+=3
					else
						if (iSimbol and &hD800) = &hD800 then
							if i < iLen-1 then
								dim as Long iSecondSG = wsText[i+1]
								if (iSecondSG and &hDC00) = &hDC00 then
									iSimbol -= &hD800
									iSimbol shl= 10
									iSimbol += &h10000
									iSecondSG -= &hDC00
									iSimbol += iSecondSG
									psz[iIndex] = (&hf0 Or (&h7 And (iSimbol Shr 18)))
									psz[iIndex+1] = (&h80 Or (&h3F And (iSimbol Shr 12)))
									psz[iIndex+2] = (&h80 Or (&h3f And (iSimbol Shr 6)))
									psz[iIndex+3] = &h80 Or (iSimbol And &h3F)
									iIndex+=4
									i+=1
									continue for
								EndIf
							EndIf
						EndIf
						psz[iIndex] = &hEF
						psz[iIndex+1] = &hBF
						psz[iIndex+2] = &hBD
						iIndex+=3
					endif
				Elseif iSimbol > &hFFFF andalso iSimbol < &h110000 Then
					psz[iIndex] = (&hf0 Or (&h7 And (iSimbol Shr 18)))
					psz[iIndex+1] = (&h80 Or (&h3F And (iSimbol Shr 12)))
					psz[iIndex+2] = (&h80 Or (&h3f And (iSimbol Shr 6)))
					psz[iIndex+3] = &h80 Or (iSimbol And &h3F)
					iIndex+=4
				Else
					psz[iIndex] = &hEF
					psz[iIndex+1] = &hBF
					psz[iIndex+2] = &hBD
					iIndex+=3
				End If
			Next
			psz[iIndex] = 0
			Function = *Cast(Zstring Ptr, psz)
			Deallocate(psz)
		else
			print "Allocated memory error in extWstring.EncodeUTF8ToUnicode!"
		endif
	endif
End Function
