/*

CLASS {NATIVE_String_functions|_CSharp}, 
	NATIVE, BITWISE, BYTES,
	UNTESTED :

IMPORT: {String_functions} .

*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

using System.Globalization;

namespace AL4
{
    public class NATIVE_String_functions
    {
        /*
-------------------------------------- 'starting / ending'

NATIVE: "///copy NATIVE_String_functions.cs" .
        
------------------------------------------ 'encoding'
                 
FUN Get_inner_encoding
|_of_strings_in_the_environment ==> {encoding} := 'UTF16' .
                 
FUN Is_encoding_supported(
    {String_functions}.{encoding} E|ncoding_DUMMY) ==> BOOL
    :
    RESULT = TRUE // C# supports all
    .

FUN Get_bytes_from_default(
	BYTE D|estination[], STR S|ource_string ), NATIVE
	: NATIVE NATIVE_Bytes_from_ascii .
			
FUN Trim_string(STR S|tring_to_trim) ==> STR :
	RESULT = S.TrimR.TrimL .
	 
FUN Trim_left_string(
STR S|tring_to_trim) ==> STR, NATIVE : @
"   for (int i = 0; i < X_S.Length; i++)"
"       if ((uint)X_S[i] > 32)"
"           return X_S.Substring(i);" .
    
FUN Trim_right_string(
STR S|tring_to_trim) ==> STR, NATIVE : @
"   for (int i = X_S.Length-1; i >= 0; i--)"
"       if ((uint)X_S[i] > 32)"
"           return X_S.Substring(0, i+1);" .

FUN Split_string_native(
STR Dest|ination_buffer[], STR S|tring_to_trim, STR By|_separator),
NATIVE : @
"string[] x = X_S.Split(new string[]{X_By}, "
    "    StringSplitOptions.None);"
    "    foreach (string s in x)"
    "        X_Dest.Add(s);" .

CONST STR:
	
	NATIVE_import_string_functions = ""

	NATIVE_Path_sep = "RESULT = "#QU"\\"#QU";"

	NATIVE_Char = "RESULT = " #QU #QU " + (char)X_I;"
	
	NATIVE_Ord = "RESULT = (int)(uint)((X_Ch + (char)0)[0]);"
	
	NATIVE_Upper = "RESULT = AL4_system.ToUpper1(X_S);"
	
	NATIVE_Lower = "RESULT = AL4_system.ToLower1(X_S);"
	
	NATIVE_Repeat = @
	"StringBuilder sb = new StringBuilder(X_What.Length * (int)X_Count);"
	"for (int i = 0; i < X_Count; i++) sb.Append(X_What);"
	"RESULT = sb.ToString();"     
	
    NATIVE_Bytes_to_ascii = @
    "    byte[] buffer = new byte[X_B.Count];"
	"	 X_B.ToBytes(buffer, 0, X_B.Count);"
	"    RESULT = Encoding.Default.GetString(buffer);"
	
	NATIVE_Bytes_to_utf8 = @
	"    byte[] buffer = new byte[X_B.Count];"
	"	 X_B.ToBytes(buffer, 0, X_B.Count);"
	"  	 RESULT = Encoding.UTF8.GetString(buffer);"
	
	NATIVE_Bytes_to_utf7 = @
	"    byte[] buffer = new byte[X_B.Count];"
	"	 X_B.ToBytes(buffer, 0, X_B.Count);"
	"  	 RESULT = Encoding.UTF7.GetString(buffer);"
	
	NATIVE_Bytes_to_utf16 = @
	"    byte[] buffer = new byte[X_B.Count];"
	"	 X_B.ToBytes(buffer, 0, X_B.Count);"
	"    RESULT = Encoding.Unicode.GetString(buffer);"
	
	NATIVE_Bytes_to_utf16_big = @
	"    byte[] buffer = new byte[X_B.Count];"
	"	 X_B.ToBytes(buffer, 0, X_B.Count);"
	"    RESULT = Encoding.BigEndianUnicode.GetString(buffer);"
	
	NATIVE_Bytes_to_utf32 = @
	"    byte[] buffer = new byte[X_B.Count];"
	"	 X_B.ToBytes(buffer, 0, X_B.Count);"
	"	 RESULT = Encoding.UTF32.GetString(buffer);"
	
	NATIVE_Bytes_to_utf32_big = @
	"    byte[] buffer = new byte[X_B.Count];"
    "	  X_B.ToBytes(buffer, 0, X_B.Count);"
    "    for (int i = 0; i < buffer.Length - 4; i+=4)"
    "    {"
    "        byte b1 = buffer[i];"
    "        byte b2 = buffer[i+1];"
    "        byte b3 = buffer[i+2];"
    "        byte b4 = buffer[i+3];"
    "        buffer[i] = b4;"
    "        buffer[i+1] = b3;"
    "        buffer[i+2] = b2;"
    "        buffer[i+3] = b1;"
    "    }"
    "    RESULT = Encoding.UTF32.GetString(buffer);"
    
    NATIVE_Bytes_from_ascii = @
    "    X_D.Clear();"
    "    byte[] buffer = Encoding.ASCII.GetBytes(X_S);"
    "    ((DynAByte)X_D).Capacity = buffer.Length;"
    "    for (int i = 0; i < buffer.Length; i++)"
    "        X_D.Add(buffer[i]);"
    
    NATIVE_Bytes_from_utf8 = @
	"    X_D.Clear();"
    "    byte[] buffer = Encoding.UTF8.GetBytes(X_S);"
    "    ((DynAByte)X_D).Capacity = buffer.Length;"
    "    for (int i = 0; i < buffer.Length; i++)"
    "        X_D.Add(buffer[i]);"
	
 	NATIVE_Bytes_from_utf7 = @
 	"    X_D.Clear();"
    "    byte[] buffer = Encoding.UTF7.GetBytes(X_S);"
    "    ((DynAByte)X_D).Capacity = buffer.Length;"
    "    for (int i = 0; i < buffer.Length; i++)"
    "        X_D.Add(buffer[i]);"
    
    NATIVE_Bytes_from_utf16 = @
    "    X_D.Clear();"
    "    byte[] buffer = Encoding.Unicode.GetBytes(X_S);"
    "    ((DynAByte)X_D).Capacity = buffer.Length;"
    "    for (int i = 0; i < buffer.Length; i++)"
    "        X_D.Add(buffer[i]);"
    
    NATIVE_Bytes_from_utf16_big_endian = @
	"    X_D.Clear();"
    "    byte[] buffer = Encoding.BigEndianUnicode.GetBytes(X_S);"
    "    ((DynAByte)X_D).Capacity = buffer.Length;"
    "    for (int i = 0; i < buffer.Length; i++)"
    "        X_D.Add(buffer[i]);"
    
    NATIVE_Bytes_from_utf32 = @
    "    X_D.Clear();"
    "    byte[] buffer = Encoding.UTF32.GetBytes(X_S);"
    "    ((DynAByte)X_D).Capacity = buffer.Length;"
    "    for (int i = 0; i < buffer.Length; i++)"
    "        X_D.Add(buffer[i]);"
    
    NATIVE_Bytes_from_utf32_big_endian = @
    "    X_D.Clear();"
    "    byte[] buffer = Encoding.UTF32.GetBytes(X_S);"
    "    for (int i = 0; i < buffer.Length; i+=4)"
    "    {"
    "        byte b1 = buffer[i];"
    "        byte b2 = buffer[i+1];"
    "        byte b3 = buffer[i+2];"
    "        byte b4 = buffer[i+3];"
    "        buffer[i] = b4;"
    "        buffer[i+1] = b3;"
    "        buffer[i+2] = b2;"
    "        buffer[i+3] = b1;"
    "    }"
    "    ((DynAByte)X_D).Capacity = buffer.Length;"
    "    for (int i = 0; i < buffer.Length; i++)"
    "        X_D.Add(buffer[i]);"
    
    NATIVE_Unicode16_to_ANSI = @
    "NATIVE_String_functions.Do_unicode16_to_ansi(X_U, X_A);" 
    
    NATIVE_Oem_to_string = @
    "X_S[1] = NATIVE_String_functions.Do_oem_to_string(X_S[0]);" 
    
    NATIVE_Ansi_bytes_to_utf8 = ""     
    .
    
    */
   		
   		[DllImport("kernel32.dll")]
		private static extern Int32 WideCharToMultiByte(
			UInt32 CodePage,
			UInt32 dwFlags,
			[MarshalAs(UnmanagedType.LPWStr)] String lpWideCharStr,
			Int32 cchWideChar,
			[Out, MarshalAs(UnmanagedType.LPArray)] Byte[] lpMultiByteStr,
			Int32 cbMultiByte, IntPtr lpDefaultChar, IntPtr lpUsedDefaultChar);

        public static void Do_unicode16_to_ansi(string U, ArrayByte A)
        {
        	const int CP_ACP = 0;
        	const int WC_COMPOSITECHECK = 0x200;
        	const int WC_DISCARDNS = 0x10;
        	const int WC_SEPCHARS = 0x20;
        	const int WC_DEFAULTCHAR = 0x40;
        	
   			int len = WideCharToMultiByte(CP_ACP,
   				WC_COMPOSITECHECK|WC_DISCARDNS|WC_SEPCHARS|WC_DEFAULTCHAR,
   				U, -1, null, 0, IntPtr.Zero, IntPtr.Zero);
   			if (len == 0) return;
   			
   			((DynAByte)A).Capacity = len;
   			byte[] r = new byte[len];
   			WideCharToMultiByte(CP_ACP,
   				WC_COMPOSITECHECK|WC_DISCARDNS|WC_SEPCHARS|WC_DEFAULTCHAR,
   				U, -1, r, r.Length, IntPtr.Zero, IntPtr.Zero);
   			for (int i = 0; i < r.Length; i++)
   				A.Add(r[i]);
        }
        
        [DllImport("user32.dll")]
        private static extern bool OemToCharBuffA(
            [MarshalAs(UnmanagedType.LPStr)] String lpszSrc,
            [Out, MarshalAs(UnmanagedType.LPArray)] Byte[] lpszDst,
            Int32 cchDstLength);
        
        public static string Do_oem_to_string(string Oem)
        {
			Byte[] Dst = new Byte[(Oem.Length)];
			if (!OemToCharBuffA(Oem, Dst, Oem.Length)) return Oem;
			Encoding uni = Encoding.GetEncoding(
				CultureInfo.CurrentCulture.TextInfo.ANSICodePage);
			string r = uni.GetString(Dst);
			return r;
        }
             

    }
}

/*
END
*/


