#if !USE_CUSTOM_VSTRING_SCRIPT
#if UNITY_ANDROID && ENABLE_IL2CPP
#define WIN32 // for alignment problems on Android ARMv7 target.
    // TODO: Android X86 target don't need this. How to tell?
#endif

namespace Giant.Common
{
    public static class Buffer
    {
        public unsafe static void Memcpy(byte[] dest, int destIndex, byte[] src, int srcIndex, int len)
        {
            fixed (byte* pDest = dest)
            fixed (byte* pSrc  = src)
            {
                Memcpy(pDest + destIndex, pSrc + srcIndex, len);
            }
        }



        public unsafe static void ZeroMemory(byte* src, long len)
        {
            while (len-- > 0)
                *(src + len) = 0;
        }



        /// <summary>
        /// Copy memory buffer content
        /// </summary>
        /// <param name="dmem">dst mem</param>
        /// <param name="smem">src mem</param>
        /// <param name="charCount">the number of char</param>
        public static unsafe void wstrcpy(char* dmem, char* smem, int charCount)
        {         
#if WIN32
            Memmove((byte*)dmem, (byte*)smem, (uint)charCount * 2);
#else
            Memmove((byte*)dmem, (byte*)smem, (ulong)charCount * 2);
#endif
        }



        public unsafe static void Memcpy(byte* dest, byte* src, int len)
        {
            Memmove(dest, src, (uint)len);
        }



#if WIN32
        public unsafe static void Memmove(byte* dest, byte* src, uint len)
#else
        public unsafe static void Memmove(byte* dest, byte* src, ulong len)      
#endif
        {
            if(dest == null || src == null)
                return;
            switch (len)
            {
                case 0:
                    return;
                case 1:
                    *dest = *src;
                    return;
                case 2:
                    *(short*)dest = *(short*)src;
                    return;
                case 3:
                    *(short*)dest = *(short*)src;
                    *(dest + 2) = *(src + 2);
                    return;
                case 4:
                    *(int*)dest = *(int*)src;
                    return;
                case 5:
                    *(int*)dest = *(int*)src;
                    *(dest + 4) = *(src + 4);
                    return;
                case 6:
                    *(int*)dest = *(int*)src;
                    *(short*)(dest + 4) = *(short*)(src + 4);
                    return;
                case 7:
                    *(int*)dest = *(int*)src;
                    *(short*)(dest + 4) = *(short*)(src + 4);
                    *(dest + 6) = *(src + 6);
                    return;
                case 8:
#if WIN32
                    *(int*)dest = *(int*)src;
                    *(int*)(dest + 4) = *(int*)(src + 4);
#else
                    *(long*)dest = *(long*)src;                
#endif
                    return;
                case 9:
#if WIN32
                    *(int*)dest = *(int*)src;
                    *(int*)(dest + 4) = *(int*)(src + 4);
#else
                    *(long*)dest = *(long*)src;
#endif
                    *(dest + 8) = *(src + 8);
                    return;
                case 10:
#if WIN32
                
                    *(int*)dest = *(int*)src;
                    *(int*)(dest + 4) = *(int*)(src + 4);
#else
                    *(long*)dest = *(long*)src;
#endif
                    *(short*)(dest + 8) = *(short*)(src + 8);
                    return;
                case 11:
#if WIN32
                    *(int*)dest = *(int*)src;
                    *(int*)(dest + 4) = *(int*)(src + 4);              
#else
                    *(long*)dest = *(long*)src;
#endif
                    *(short*)(dest + 8) = *(short*)(src + 8);
                    *(dest + 10) = *(src + 10);
                    return;
                case 12:
#if WIN32
                    *(int*)dest = *(int*)src;
                    *(int*)(dest + 4) = *(int*)(src + 4);
#else
                    *(long*)dest = *(long*)src;
#endif
                    *(int*)(dest + 8) = *(int*)(src + 8);
                    return;
                case 13:
#if WIN32
                    *(int*)dest = *(int*)src;
                    *(int*)(dest + 4) = *(int*)(src + 4);
#else
                    *(long*)dest = *(long*)src;
#endif
                    *(int*)(dest + 8) = *(int*)(src + 8);
                    *(dest + 12) = *(src + 12);
                    return;
                case 14:
#if WIN32
                    *(int*)dest = *(int*)src;
                    *(int*)(dest + 4) = *(int*)(src + 4);
#else
                    *(long*)dest = *(long*)src;
#endif
                    *(int*)(dest + 8) = *(int*)(src + 8);
                    *(short*)(dest + 12) = *(short*)(src + 12);
                    return;
                case 15:
#if WIN32
                    *(int*)dest = *(int*)src;
                    *(int*)(dest + 4) = *(int*)(src + 4);
#else
                    *(long*)dest = *(long*)src;
#endif
                    *(int*)(dest + 8) = *(int*)(src + 8);
                    *(short*)(dest + 12) = *(short*)(src + 12);
                    *(dest + 14) = *(src + 14);
                    return;
                case 16:
#if WIN32
                    *(int*)dest = *(int*)src;
                    *(int*)(dest + 4) = *(int*)(src + 4);
                    *(int*)(dest + 8) = *(int*)(src + 8);
                    *(int*)(dest + 12) = *(int*)(src + 12);
#else
                    *(long*)dest = *(long*)src;
                    *(long*)(dest + 8) = *(long*)(src + 8);                    
#endif
                    return;
                default:
                    break;
            }

            if (((int)dest & 3) != 0)
            {
                if (((int)dest & 1) != 0)
                {
                    *dest = *src;
                    src++;
                    dest++;
                    len--;
                    if (((int)dest & 2) == 0)
                        goto Aligned;
                }
                *(short*)dest = *(short*)src;
                src += 2;
                dest += 2;
                len -= 2;
                Aligned:
                ;
            }

#if WIN32
           
#else
            if (((int)dest & 4) != 0)
            {
                *(int*)dest = *(int*)src;
                src += 4;
                dest += 4;
                len -= 4;
            }
#endif

#if WIN32
            uint count = len / 16;       
#else
            ulong count = len / 16;
#endif
            while (count > 0)
            {
#if WIN32
                ((int*)dest)[0] = ((int*)src)[0];
                ((int*)dest)[1] = ((int*)src)[1];
                ((int*)dest)[2] = ((int*)src)[2];
                ((int*)dest)[3] = ((int*)src)[3];
#else
                ((long*)dest)[0] = ((long*)src)[0];
                ((long*)dest)[1] = ((long*)src)[1];              
#endif
                dest += 16;
                src += 16;
                count--;
            }

            if ((len & 8) != 0)
            {
#if WIN32
                ((int*)dest)[0] = ((int*)src)[0];
                ((int*)dest)[1] = ((int*)src)[1];
#else
                ((long*)dest)[0] = ((long*)src)[0];              
#endif
                dest += 8;
                src += 8;
            }
            if ((len & 4) != 0)
            {
                ((int*)dest)[0] = ((int*)src)[0];
                dest += 4;
                src += 4;
            }
            if ((len & 2) != 0)
            {
                ((short*)dest)[0] = ((short*)src)[0];
                dest += 2;
                src += 2;
            }
            if ((len & 1) != 0)
                *dest = *src;

            return;
        }
    }
}
#endif