#if !USE_CUSTOM_VSTRING_SCRIPT
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Giant.Common
{
public enum AllocType
    {
        None        = 0,
        Tmp         = 1,
        Persistent  = 2,
    }



    public class VString : IDisposable
    {
#region Static and Const
        private static VString s_Empty = null;
        /// <summary>
        /// Static Empty string
        /// </summary>
        public unsafe static VString Empty
        {
            get
            {
                if(null == s_Empty)
                {
                    s_Empty = VStringPool.Instance.GetString(0, AllocType.Persistent);
                    *(s_Empty.buffer) = '\0';
                }
                return s_Empty;
            }
        }



        public static VString From(string _Value, AllocType _AllocType)
        {
            if (null == _Value) _Value = string.Empty;
            VString tSesult = VStringPool.Instance.GetString(_Value.Length, _AllocType);
            return tSesult.CopyFrom(_Value);
        }



        public static VString From(int _Value, AllocType _AllocType)
        {
            VString tResult = VStringPool.Instance.GetString(1, _AllocType);
            tResult.Fill(_Value);
            return tResult;
        }



        /// <summary>
        /// Is the string  empty or null
        /// </summary>
        public static bool IsNullOrEmpty(VString _Value)
        {
            return (null == (object)_Value || _Value.Length == 0);
        }



        /// <summary>
        /// Concat two string in one string
        /// </summary>
        public static unsafe VString Concat(string _Arg0, string _Arg1, AllocType _AllocType = AllocType.Tmp)
        {
            if (null == _Arg0) _Arg0 = string.Empty;
            if (null == _Arg1) _Arg1 = string.Empty;
            int tLength0 = _Arg0.Length;
            int tLength1 = _Arg1.Length;
            int tLength = tLength0 + tLength1;
            VString tResult = VStringPool.Instance.GetString(tLength, _AllocType);
            char* pDest = tResult.buffer;
            fixed (char* pSrc0 = _Arg0)
            fixed (char* pSrc1 = _Arg1)
            {
                Buffer.wstrcpy(pDest, pSrc0, tLength0);
                Buffer.wstrcpy(pDest + tLength0, pSrc1, tLength1);
                *(pDest + tLength) = '\0';
            }
            tResult.m_Length = tLength;
            return tResult;
        }



        /// <summary>
        /// Concat three string in one string
        /// </summary>
        /// <param name="_Arg0">sting for concating</param>
        /// <param name="_Arg1">sting for concating</param>
        /// <param name="_Arg2">sting for concating</param>
        /// <returns>The String object for concat result</returns>
        public static VString Concat(string _Arg0, string _Arg1, string _Arg2, AllocType _AllocType = AllocType.Tmp)
        {
            if (null == _Arg0) _Arg0 = string.Empty;
            if (null == _Arg1) _Arg1 = string.Empty;
            if (null == _Arg2) _Arg2 = string.Empty;
            int tLength0 = _Arg0.Length;
            int tLength1 = _Arg1.Length;
            int tLength2 = _Arg2.Length;
            int tLength = tLength0 + tLength1 + tLength2;
            VString tResult = VStringPool.Instance.GetString(tLength, _AllocType);
            unsafe
            {
                fixed (char* pSrc0 = _Arg0)
                fixed (char* pSrc1 = _Arg1)
                fixed (char* pSrc2 = _Arg2)
                {
                    char* pDest = tResult.buffer;
                    Buffer.wstrcpy(pDest, pSrc0, tLength0);
                    pDest += tLength0;
                    Buffer.wstrcpy(pDest, pSrc1, tLength1);
                    pDest += tLength1;
                    Buffer.wstrcpy(pDest, pSrc2, tLength2);
                    *(pDest + tLength2) = '\0';
                }
            }
            tResult.m_Length = tLength;
            return tResult;
        }



        /// <summary>
        /// Concat four string in one string
        /// </summary>
        /// <param name="arg0">sting for concating</param>
        /// <param name="arg1">sting for concating</param>
        /// <param name="arg2">sting for concating</param>
        /// <param name="arg3">sting for concating</param>
        /// <returns>The String object for concat result</returns>
        public static VString Concat(string _Arg0, string _Arg1, string _Arg2, string _Arg3, AllocType _AllocType = AllocType.Tmp)
        {
            if (null == _Arg0) _Arg0 = string.Empty;
            if (null == _Arg1) _Arg1 = string.Empty;
            if (null == _Arg2) _Arg2 = string.Empty;
            if (null == _Arg3) _Arg3 = string.Empty;
            int tLength0 = _Arg0.Length;
            int tLength1 = _Arg1.Length;
            int tLength2 = _Arg2.Length;
            int tLength3 = _Arg3.Length;
            int tLength = tLength0 + tLength1 + tLength2 + tLength3;
            VString tResult = VStringPool.Instance.GetString(tLength, _AllocType);
            unsafe
            {
                fixed (char* pSrc0 = _Arg0)
                fixed (char* pSrc1 = _Arg1)
                fixed (char* pSrc2 = _Arg2)
                fixed (char* pSrc3 = _Arg3)
                {
                    char* pDest = tResult.buffer;
                    Buffer.wstrcpy(pDest, pSrc0, tLength0);
                    pDest += tLength0;
                    Buffer.wstrcpy(pDest, pSrc1, tLength1);
                    pDest += tLength1;
                    Buffer.wstrcpy(pDest, pSrc2, tLength2);
                    pDest += tLength2;
                    Buffer.wstrcpy(pDest, pSrc3, tLength3);
                    *(pDest + tLength3) = '\0';
                }
            }
            tResult.m_Length = tLength;
            return tResult;
        }




        /// <summary>
        /// Concat the string array in one string
        /// </summary>
        /// <param name="_Args">array of string</param>
        /// <returns>The String object for concat result</returns>
        public static VString Concat(AllocType _AllocType = AllocType.Tmp, params string[] _Args)
        {
            int tTotalLength = 0;
            int tCount = _Args.Length;
            for (int tIdx = 0; tIdx < tCount; ++tIdx)
            {
                var tStr = _Args[tIdx];
                if (null == tStr)
                    _Args[tIdx] = string.Empty;
                else
                    tTotalLength += tStr.Length;
            }
            VString tResult = VStringPool.Instance.GetString(tTotalLength, _AllocType);
            unsafe
            {
                char* pDest = tResult.buffer;
                for (int tIdx = 0; tIdx < tCount; ++tIdx)
                {
                    var tStr = _Args[tIdx];
                    var tLength = tStr.Length;
                    if (tLength > 0)
                    {
                        fixed (char* pSrc = tStr)
                            Buffer.wstrcpy(pDest, pSrc, tLength);
                        pDest += tLength;
                    }
                }
                *pDest = '\0';
            }
            tResult.m_Length = tTotalLength;
            return tResult;
        }



        /// <summary>
        /// Concat two string in one string
        /// </summary>
        /// <param name="_Arg0">sting for concating</param>
        /// <param name="_Arg1">sting for concating</param>
        /// <returns>The String object for concat result</returns>
        public static unsafe VString Concat(VString _Arg0, VString _Arg1, AllocType _AllocType = AllocType.Tmp)
        {
            if (null == _Arg0) _Arg0 = VString.Empty;
            if (null == _Arg1) _Arg1 = VString.Empty;
            int tLength0 = _Arg0.Length;
            int tLength1 = _Arg1.Length;
            int tLength = tLength0 + tLength1;
            VString tResult = VStringPool.Instance.GetString(tLength, _AllocType);
            char* pDest = tResult.buffer;
            Buffer.wstrcpy(pDest, _Arg0.buffer, tLength0);
            pDest += tLength0;
            Buffer.wstrcpy(pDest, _Arg1.buffer, tLength1);
            *(pDest + tLength1) = '\0';
            tResult.m_Length = tLength;
            return tResult;
        }



        /// <summary>
        /// Concat three string in one string
        /// </summary>
        /// <param name="_Arg0">sting for concating</param>
        /// <param name="_Arg1">sting for concating</param>
        /// <param name="_Arg2">sting for concating</param>
        /// <returns>The String object for concat result</returns>
        public unsafe static VString Concat(VString _Arg0, VString _Arg1, VString _Arg2, AllocType _AllocType = AllocType.Tmp)
        {
            if (null == _Arg0) _Arg0 = VString.Empty;
            if (null == _Arg1) _Arg1 = VString.Empty;
            if (null == _Arg2) _Arg2 = VString.Empty;
            int tLength0 = _Arg0.Length;
            int tLength1 = _Arg1.Length;
            int tLength2 = _Arg2.Length;
            int tLength = tLength0 + tLength1 + tLength2;
            VString tResult = VStringPool.Instance.GetString(tLength, _AllocType);
            char* pDest = tResult.buffer;
            Buffer.wstrcpy(pDest, _Arg0.buffer, tLength0);
            pDest += tLength0;
            Buffer.wstrcpy(pDest, _Arg1.buffer, tLength1);
            pDest += tLength1;
            Buffer.wstrcpy(pDest, _Arg2.buffer, tLength2);
            *(pDest + tLength2) = '\0';
            tResult.m_Length = tLength;
            return tResult;
        }



        /// <summary>
        /// Concat four string in one string
        /// </summary>
        /// <param name="_Arg0">sting for concating</param>
        /// <param name="_Arg1">sting for concating</param>
        /// <param name="_Arg2">sting for concating</param>
        /// <param name="_Arg3">sting for concating</param>
        /// <returns>The String object for concat result</returns>
        public unsafe static VString Concat(VString _Arg0, VString _Arg1, VString _Arg2, VString _Arg3, AllocType _AllocType = AllocType.Tmp)
        {
            if (null == _Arg0) _Arg0 = VString.Empty;
            if (null == _Arg1) _Arg1 = VString.Empty;
            if (null == _Arg2) _Arg2 = VString.Empty;
            if (null == _Arg3) _Arg3 = VString.Empty;
            int tLength0 = _Arg0.Length;
            int tLength1 = _Arg1.Length;
            int tLength2 = _Arg2.Length;
            int tLength3 = _Arg3.Length;
            int tLength = tLength0 + tLength1 + tLength2 + tLength3;
            VString tResult = VStringPool.Instance.GetString(tLength, _AllocType);
            char* pDest = tResult.buffer;
            Buffer.wstrcpy(pDest, _Arg0.buffer, tLength0);
            pDest += tLength0;
            Buffer.wstrcpy(pDest, _Arg1.buffer, tLength1);
            pDest += tLength1;
            Buffer.wstrcpy(pDest, _Arg1.buffer, tLength2);
            pDest += tLength2;
            Buffer.wstrcpy(pDest, _Arg1.buffer, tLength3);
            *(pDest + tLength3) = '\0';
            tResult.m_Length = tLength;
            return tResult;
        }



        /// <summary>
        /// Concat the string array in one string
        /// </summary>
        /// <param name="_Args">array of string</param>
        /// <returns>The String object for concat result</returns>
        public static VString Concat(AllocType _AllocType = AllocType.Tmp, params VString[] _Args)
        {
            return Concat(_Args, _Args.Length, _AllocType);
        }



        /// <summary>
        /// Concat the string array in one string
        /// </summary>
        /// <param name="_Args">array of string</param>
        /// <param name="_Count">process first count</param>
        /// <returns>The String object for concat result</returns>
        public static VString Concat(VString[] _Args, int _Count, AllocType _AllocType = AllocType.Tmp)
        {
            int tTotalLength = 0;
            for (int tIdx = 0; tIdx < _Count; ++tIdx)
            {
                var tStr = _Args[tIdx];
                if (null == tStr)
                    _Args[tIdx] = VString.Empty;
                else
                    tTotalLength += tStr.Length;
            }
            VString tResult = VStringPool.Instance.GetString(tTotalLength, AllocType.Tmp);
            unsafe
            {
                char* pDest = tResult.buffer;
                for (int tIdx = 0; tIdx < _Count; ++tIdx)
                {
                    var tStr = _Args[tIdx];
                    var tLength = tStr.Length;
                    if (tLength > 0)
                    {
                        Buffer.wstrcpy(pDest, tStr.buffer, tLength);
                        pDest += tLength;
                    }
                }
                *pDest = '\0';
            }
            tResult.m_Length = tTotalLength;
            return tResult;
        }
#endregion



#if DISPOSE_LEAK_DETECT
        private DisposeSentinel m_Sentinel;
        public void EnableDisposeSentinel()
        {
            if (m_Sentinel == null && (m_AllocType == AllocType.Tmp || m_AllocType == AllocType.Persistent))
                m_Sentinel = new DisposeSentinel();
        }
#endif



        private enum TrimType
        {
            Head = 0,
            Tail = 1,
            Both = 2,
        }



        /// <summary>
        /// Memory for string
        /// </summary>
        private Int64 m_MemBuffer = 0;



        /// <summary>
        /// String length;
        /// </summary>
        private int m_Length = 0;
        public int Length
        {
            get { return m_Length; }
        }



        /// <summary>
        /// Capacity of memory
        /// </summary>
        private int m_Capacity = 0;
        /// <summary>
        /// The memory capacity
        /// </summary>
        public int capacity
        {
            get { return m_Capacity; }
        }



        /// <summary>
        /// String hash code
        /// </summary>
        private int m_HashCode = 0;
        /// <summary>
        /// Gets the string hash code
        /// </summary>
        public int HashCode
        {
            get { return m_HashCode; }
        }



        /// <summary>
        /// The type of memory allocator
        /// </summary>
        private AllocType m_AllocType = AllocType.None;
        /// <summary>
        /// The type of memory allocator
        /// </summary>
        public AllocType allocType
        {
            get { return m_AllocType; }
        }



        /// <summary>
        /// in string pool
        /// </summary>
        public bool inStringPool = false;



        /// <summary>
        /// has memory freed
        /// </summary>
        public bool disposed
        {
            get { return 0 == m_MemBuffer; }
        }



        /// <summary>
        /// Gets the char buffer
        /// </summary>
        public unsafe char* buffer
        {
            get { return (char*)m_MemBuffer; }
        }



        /// <summary>
        /// Gets the character at a specified position.
        /// </summary>
        public unsafe char this[int _Index]
        {
            get
            {
                if (_Index < 0 || _Index >= m_Length)
                    throw new IndexOutOfRangeException("_Index");
                return buffer[_Index];
            }
            set
            {
                if (_Index < 0 || _Index >= m_Length)
                    throw new IndexOutOfRangeException("_Index");
                buffer[_Index] = value;
            }
        }



        public VString(AllocType _AllocType = AllocType.Persistent)
        {
            m_Length        = 0;
            m_Capacity      = 0;
            m_AllocType     = _AllocType;
            inStringPool    = false;
        }



        public VString(int _Length, AllocType _AllocType):this(_AllocType)
        {
            AllocMemoryInternal(_Length + 1);
        }



        public VString(char[] _Chars, AllocType _AllocType) : this(_AllocType)
        {
            if(null != _Chars)
            {
                var tLength = _Chars.Length;
                Allocate(tLength, _AllocType);
                unsafe
                {
                    char* pDst = buffer;
                    fixed (char* pSrc = _Chars)
                    {
                        Buffer.wstrcpy(pDst, pSrc, tLength);
                        *(pDst + tLength) = '\0';
                    }
                }
                m_Length = tLength;
            }
        }



        public VString(string _Value, AllocType _AllocType):this(_AllocType)
        {
            CopyFrom(_Value);
        }



        /// <summary>
        /// Destructor
        /// </summary>
        ~VString()
        {
            Dispose();
        }



        /// <summary>
        /// Gets memory for string
        /// </summary>
        internal unsafe void Allocate(int _Length, AllocType _AllocType)
        {
            int tNewCapacity = _Length + 1;
            m_AllocType = _AllocType;
            m_Length = 0;
            if (m_Capacity < tNewCapacity || 0 == m_MemBuffer)
            {
                FreeMemory();
                AllocMemoryInternal(tNewCapacity);
            }
            *buffer = '\0';
        }



        /// <summary>
        /// Gets memory to the memory buffer
        /// </summary>
        private void AllocMemoryInternal(int _Capacity)
        {
            m_MemBuffer = AllocInternal(_Capacity, m_AllocType);
            m_Capacity = _Capacity;
        }



        private Int64 AllocInternal(int _Capacity, AllocType _AllocType)
        {            
            //默认一个字符两个字节
            Int64 tBuffer = 0;
            if (_AllocType == AllocType.Persistent)
                tBuffer = CharMemoryPool.Instance.AllocMemory(_Capacity * 2);
            else
                tBuffer = NativeRingBuffer.Instance.AllocMemory(_Capacity * 2);
            return tBuffer;
        }



        /// <summary>
        /// Replace the string memory buffer
        /// </summary>
        private void Assign(Int64 _NewBuffer, int _Length, int _Capacity)
        {
            FreeMemory();
            m_MemBuffer = _NewBuffer;
            if(0 != m_MemBuffer)
            {
                m_Capacity = _Capacity;
                m_Length = _Length;
            }
        }



        /// <summary>
        /// Return memory to the memory buffer
        /// </summary>
        internal void FreeMemory()
        {
            if(0 != m_MemBuffer)
            {
                if (m_AllocType == AllocType.Persistent)
                {
                    IntPtr tBuffer = new IntPtr(m_MemBuffer);
                    CharMemoryPool.Instance.FreeMemory(ref tBuffer, m_Capacity * 2);
                }
                m_MemBuffer = 0;
                //临时内存不需要回收
            }
            m_Length    = 0;
            m_Capacity  = 0;
            m_HashCode  = 0;
        }



        /// <summary>
        /// Dispose string, return back memory to memory pool
        /// This function must be explicit call
        /// </summary>
        public void Dispose()
        {
            VStringPool.Instance.FreeString(this);
            FreeMemory();
            GC.SuppressFinalize(this);
#if DISPOSE_LEAK_DETECT
                if(null != m_Sentinel)
                {
                    m_Sentinel.Dispose();
                    m_Sentinel = null;
                }
#endif
        }



        private void CheckValid()
        {
            if(0 == m_MemBuffer)
                throw new NotImplementedException("m_MemBuffer has not allocated yet");
        }



        /// <summary>
        ///Gets the char array, allocate managed memory    
        /// </summary>
        public char[] ToCharArray()
        {
            CheckValid();
            int tLength = m_Length + 1;
            char[] tChars = new char[tLength];
            if (tLength > 0)
                Marshal.Copy(new IntPtr(m_MemBuffer), tChars, 0, tLength);
            return tChars;
        }



        /// <summary>
        ///Gets the char list, no allocate
        /// </summary>
        public unsafe void ToCharArray(List<char> _CharList)
        {
            if(null != _CharList)
            {
                _CharList.Clear();
                CheckValid();
                if (_CharList.Capacity < m_Length)
                    _CharList.Capacity = m_Length;
                char* tP = buffer;
                for (int tIdx = 0; tIdx < m_Length; tIdx++)
                    _CharList.Add(*(tP++));
            }
        }



        /// <summary>
        /// replace the old content with chars in string
        /// </summary>
        public VString CopyFrom(string _Value)
        {
            m_HashCode = 0;
            if (null == _Value) _Value = string.Empty;
            int tLength = _Value.Length;
            Allocate(tLength, m_AllocType);
            unsafe
            {
                char* pDst = buffer;
                fixed (char* pSrc = _Value)
                {
                    Buffer.wstrcpy(pDst, pSrc, tLength);
                    *(pDst + tLength) = '\0';
                }
            }
            m_Length = tLength;
            return this;
        }



        /// <summary>
        /// Gets a sub string
        /// </summary>
        public VString Substring(int _StartIndex, bool _NoAlloc = false)
        {
            if (_NoAlloc)
                return SubstringNonAlloc(_StartIndex, m_Length - _StartIndex);
            else
                return SubstringAlloc(_StartIndex, m_Length - _StartIndex);
        }



        public VString Substring(int _StartIndex, int _Length, bool _NoAlloc = false)
        {
            if (_NoAlloc)
                return SubstringNonAlloc(_StartIndex, _Length);
            else
                return SubstringAlloc(_StartIndex, _Length);
        }



        /// <summary>
        /// Get a sub string
        /// </summary>
        private VString SubstringAlloc(int _StartIndex, int _Length)
        {
            //Bounds Checking.
            CheckValid();
            if (_StartIndex < 0)
                throw new ArgumentOutOfRangeException("ArgumentOutOfRange_StartIndex");
            if (_StartIndex > m_Length)
                throw new ArgumentOutOfRangeException("ArgumentOutOfRange_StartIndexLargerThanLength");
            if (_Length < 0)
                throw new ArgumentOutOfRangeException("ArgumentOutOfRange_NegativeLength");
            if (_StartIndex > m_Length - _Length)
                throw new ArgumentOutOfRangeException("ArgumentOutOfRange_IndexLength");

            VString tResult = VStringPool.Instance.GetString(_Length, m_AllocType);
            if(_Length > 0)
            {
                unsafe
                {
                    char* pDest = tResult.buffer;
                    char* pSrc = buffer;
                    Buffer.wstrcpy(pDest, pSrc + _StartIndex, _Length);
                    *(pDest + _Length) = '\0';
                }
                tResult.m_Length = _Length;
            }
            return tResult;
        }



        /// <summary>
        /// Gets a sub string.The results will replace the original string buffer
        /// Must be faster than the Substring interface
        /// </summary>
        private VString SubstringNonAlloc(int _StartIndex, int _Length)
        {
            //Bounds Checking.
            CheckValid();
            if (_StartIndex < 0 || _StartIndex > Length || _Length < 0 || _StartIndex > Length - _Length)
                throw new System.ArgumentException();

            if (_StartIndex != 0 || _Length != m_Length)
            {
                m_HashCode = 0;
                unsafe
                {
                    char* pDest = buffer;
                    Buffer.wstrcpy(pDest, pDest + _StartIndex, _Length);
                    *(pDest + _Length) = '\0';
                }
                m_Length = _Length;
            }
            return this;
        }



        /// <summary>
        /// Return C# string object
        /// </summary>
        /// <returns>string object</returns>
        public unsafe override string ToString()
        {
            return new string(buffer);
        }



        /// <summary>
        /// Insert a string to 
        /// </summary>
        /// <param name="_StartIndex">The index of start insert</param>
        /// <param name="_NewValue">string for inserting</param>
        /// <returns>True: insert success. False: insert failed</returns>
        [System.Security.SecuritySafeCritical]
        public VString Insert(int _StartIndex, VString _NewValue, bool _NoAlloc = true)
        {
            if (_NoAlloc)
                return InsertNonAlloc(_StartIndex, _NewValue);
            else
                return InsertAlloc(_StartIndex, _NewValue);
        }



        private  VString InsertAlloc(int _StartIndex, VString _NewValue)
        {
            CheckValid();
            if (null == _NewValue)
                throw new ArgumentNullException("_NewValue");
            if (_StartIndex < 0 || _StartIndex > m_Length)
                throw new ArgumentOutOfRangeException("_StartIndex is negative or greater than the length of this instance");

            int tOldLength = m_Length;
            int tInsertLength = _NewValue.Length;
            int tNewLength = tOldLength + tInsertLength;
            VString tResult = VStringPool.Instance.GetString(tNewLength, m_AllocType);
            unsafe
            {
                char* pDest = tResult.buffer;
                char* pSrcInsert = _NewValue.buffer;
                char* pSrcOld = buffer;
                {
                    //前半段
                    if (_StartIndex > 0)
                        Buffer.wstrcpy(pDest, pSrcOld, _StartIndex);
                    //后半段
                    if (_StartIndex < tOldLength)
                        Buffer.wstrcpy(pDest + _StartIndex + tInsertLength, pSrcOld + _StartIndex, tOldLength - _StartIndex);
                    //插入段
                    Buffer.wstrcpy(pDest + _StartIndex, pSrcInsert, tInsertLength);
                    *(pDest + tNewLength) = '\0';
                }
            }
            tResult.m_Length = tNewLength;
            return tResult;
        }



        private VString InsertNonAlloc(int _StartIndex, VString _NewValue)
        {
            CheckValid();
            if (null == _NewValue)
                throw new ArgumentNullException("_NewValue");
            if (_StartIndex < 0 || _StartIndex > m_Length)
                throw new ArgumentOutOfRangeException("_StartIndex is negative or greater than the length of this instance");

            int tOldLength = m_Length;
            int tInsertLength = _NewValue.Length;
            int tNewLength = tOldLength + tInsertLength;
            if (tNewLength == 0)
                return this;

            m_HashCode = 0;
            int tLength = tNewLength + 1;
            Int64 tNewBuffer = AllocInternal(tLength, m_AllocType);
            unsafe
            {
                char* pDest = (char*)tNewBuffer;
                char* pSrcInsert = _NewValue.buffer;
                char* pSrcOld = buffer;
                {
                    //前半段
                    if (_StartIndex > 0)
                        Buffer.wstrcpy(pDest, pSrcOld, _StartIndex);
                    //后半段
                    if (_StartIndex < tOldLength)
                        Buffer.wstrcpy(pDest + _StartIndex + tInsertLength, pSrcOld + _StartIndex, tOldLength - _StartIndex);
                    //插入段
                    Buffer.wstrcpy(pDest + _StartIndex, pSrcInsert, tInsertLength);
                    *(pDest + tNewLength) = '\0';
                }
            }
            Assign(tNewBuffer, tNewLength, tLength);
            return this;
        }



        /// <summary>
        /// Convert String to lower
        /// </summary>
        /// <returns>The XString object</returns>
        public VString ToLower(bool _NoAlloc = true)
        {
            if (_NoAlloc)
                return ToLowerNonAlloc();
            else
                return ToLowerAlloc();
        }



        private VString ToLowerAlloc()
        {
            VString tResult = VStringPool.Instance.GetString(m_Length, m_AllocType);
            unsafe
            {
                char* pDest = tResult.buffer;
                char* pSrc = buffer;
                {
                    for (int tIdx = 0; tIdx < m_Length; ++tIdx)
                    {
                        char tChar = *pSrc;
                        if ('A' <= tChar && tChar <= 'Z')
                            tChar = (char)(tChar | 0x20);
                        *pDest = tChar;
                        pSrc++;
                        pDest++;
                    }
                }
            }
            tResult.m_Length = m_Length;
            return tResult;
        }



        /// <summary>
        /// Convert String to lower case
        /// Must be faster than ToLower interface
        /// </summary>
        private VString ToLowerNonAlloc()
        {
            CheckValid();
            m_HashCode = 0;
            unsafe
            {
                char* pDest = buffer;
                {
                    for (int tIdx = 0; tIdx < m_Length; ++tIdx)
                    {
                        char tChar = *pDest;
                        if ('A' <= tChar && tChar <= 'Z')
                            *pDest = (char)(tChar | 0x20);
                        pDest++;
                    }
                }
            }
            return this;
        }



        /// <summary>
        /// Convert String to upper case
        /// </summary>
        /// <returns>The XString object</returns>
        public VString ToUpper(bool _NoAlloc = false)
        {
            if (_NoAlloc)
                return ToUpperNonAlloc();
            else
                return ToUpperAlloc();
        }



        private VString ToUpperAlloc()
        {
            VString tResult = VStringPool.Instance.GetString(m_Length, m_AllocType);
            unsafe
            {
                char* pDest = tResult.buffer;
                char* pSrc = buffer;
                {
                    for (int tIdx = 0; tIdx < m_Length; ++tIdx)
                    {
                        char tChar = pSrc[tIdx];
                        if (tChar >= 'a' && tChar <= 'z')
                            tChar = (char)(tChar - 0x20);
                        *pDest = tChar;
                        pDest++;
                        pSrc++;
                    }
                }
            }
            tResult.m_Length = m_Length;
            return tResult;
        }



        /// <summary>
        /// Convert String to upper case
        /// Must be faster than ToUpper interface
        /// </summary>
        private VString ToUpperNonAlloc()
        {
            CheckValid();
            m_HashCode = 0;
            unsafe
            {
                char* pSrc = buffer;
                char* pDest = pSrc;
                {
                    for (int tIdx = 0; tIdx < m_Length; ++tIdx)
                    {
                        char tChar = *pDest;
                        if (tChar >= 'a' && tChar <= 'z')
                            *pDest = (char)(tChar - 0x20);
                        pDest++;
                    }
                }
            }
            return this;
        }



        /// <summary>
        /// Replace the old char with a new char
        /// </summary>
        /// <param name="_OldChar">Char is replaced</param>
        /// <param name="_NewChar">Replacement of char</param>
        public VString Replace(char _OldChar, char _NewChar, bool _NoAlloc = false)
        {
            if (_NoAlloc)
                return ReplaceNonAlloc(_OldChar, _NewChar);
            else
                return ReplaceAlloc(_OldChar, _NewChar);
        }



        private VString ReplaceNonAlloc(char _OldChar, char _NewChar)
        {
            CheckValid();
            m_HashCode = 0;
            unsafe
            {
                char* pDest = buffer;
                for (int tIdx = 0; tIdx < m_Length; ++tIdx)
                {
                    if (*pDest == _OldChar)
                        *pDest = _NewChar;
                    pDest++;
                }
            }
            return this;
        }



        /// <summary>
        /// Replace the old char with a new char
        /// </summary>
        /// <param name="_OldChar">Char is replaced</param>
        /// <param name="_NewChar">Replacement of char</param>
        private VString ReplaceAlloc(char _OldChar, char _NewChar)
        {
            VString tResult = VStringPool.Instance.GetString(m_Length, m_AllocType);
            unsafe
            {
                char* pDest = tResult.buffer;
                char* pSrc = buffer;
                {
                    for (int tIdx = 0; tIdx < m_Length; ++tIdx)
                    {
                        char tChar = pSrc[tIdx];
                        if (tChar == _OldChar)
                            tChar = _NewChar;
                        *pDest = tChar;
                        pDest++;
                        pSrc++;
                    }
                }
            }
            tResult.m_Length = m_Length;
            return tResult;
        }



        private VString Replace(VString _OldValue, VString _NewValue, bool _CaseSensitive = true, bool _NoAlloc = true)
        {
            if (_NoAlloc)
                return ReplaceNonAlloc(_OldValue, _NewValue, _CaseSensitive);
            else
                return ReplaceAlloc(_OldValue, _NewValue, _CaseSensitive);
        }



        /// <summary>
        /// Replace the old string with  new string
        /// </summary>
        /// <param name="_OldValue">String is replaced</param>
        /// <param name="_NewValue">Replacement of string</param>
        /// <param name="_CaseSensitive">CaseSensitive</param>
        private VString ReplaceAlloc(VString _OldValue, VString _NewValue, bool _CaseSensitive = true)
        {
            if (null == _OldValue)
                throw new ArgumentNullException("_OldValue");
            int tWordLength = _OldValue.Length;
            if (tWordLength == 0)
                throw new ArgumentException("_OldValue is the empty string");
           
            if (tWordLength > m_Length)
                return this.Clone();

            int tStartIndex = 0;
            int tOffset = -1;
            unsafe
            {
                int* tOffsetArray = stackalloc int[m_Length - tWordLength + 1];
                int tOffsetCount = 0;
                do
                {
                    tOffset = IndexOf(_OldValue, tStartIndex, _CaseSensitive);
                    if (tOffset >= 0)
                    {
                        tOffsetArray[0] = tOffset;
                        tOffsetCount++;
                        tStartIndex = tOffset + tWordLength;
                    }
                    else
                        break;
                } while (true);

                int tReplaceLenth   = _NewValue.Length;
                int tNewLength      = m_Length - tWordLength * tOffsetCount + tReplaceLenth * tOffsetCount;
                VString tResult    = VStringPool.Instance.GetString(tNewLength, m_AllocType);
                char* pDest         = tResult.buffer;
                char* pSrcA         = buffer;
                char* pSrcB         = _NewValue.buffer;
                int tLastReplaceEnd = 0;
                for (int tIdx = 0; tIdx < tOffsetCount; ++tIdx)
                {
                    tOffset         = tOffsetArray[tIdx];
                    int tLength     = tOffset - tLastReplaceEnd;
                    if (tLength > 0)
                    {
                        Buffer.wstrcpy(pDest, pSrcA, tLength);
                        pDest += tLength;
                    }
                    Buffer.wstrcpy(pDest, pSrcB, tReplaceLenth);
                    tLastReplaceEnd = tOffset + tWordLength;
                    pDest += tReplaceLenth;
                }

                int tLeft = m_Length - tLastReplaceEnd;
                if (tLeft > 0)
                    Buffer.wstrcpy(pDest, pSrcA + tLastReplaceEnd, tLeft);

                *(pDest + tNewLength) = '\0';
                tResult.m_Length = tNewLength;
                return tResult;
            }
        }



        /// <summary>
        /// Replace the old string with  new string
        /// </summary>
        /// <param name="_OldValue">String is replaced</param>
        /// <param name="_NewValue">Replacement of string</param>
        /// <param name="_CaseSensitive">CaseSensitive</param>
        private VString ReplaceNonAlloc(VString _OldValue, VString _NewValue, bool _CaseSensitive = true)
        {
            if (null == _OldValue)
                throw new ArgumentNullException("_OldValue");
            int tWordLength = _OldValue.Length;
            if (tWordLength == 0)
                throw new ArgumentException("_OldValue is the empty string");
            if (tWordLength > m_Length)
                return this;

            m_HashCode = 0;
            int tStartIndex = 0;
            int tOffset = -1;
            unsafe
            {
                int* tOffsetArray = stackalloc int[m_Length - tWordLength + 1];
                int tOffsetCount = 0;
                do
                {
                    tOffset = IndexOf(_OldValue, tStartIndex, _CaseSensitive);
                    if (tOffset >= 0)
                    {
                        tOffsetArray[0] = tOffset;
                        tOffsetCount++;
                        tStartIndex = tOffset + tWordLength;
                    }
                    else
                        break;
                } while (true);

                int tReplaceLenth = _NewValue.Length;
                int tNewLength = m_Length - tWordLength * tOffsetCount + tReplaceLenth * tOffsetCount;
                Int64 tResult = AllocInternal(tNewLength + 1, m_AllocType);
                char* pDest = (char*)tResult;
                char* pSrcA = buffer;
                char* pSrcB = _NewValue.buffer;
                int tLastReplaceEnd = 0;
                for (int tIdx = 0; tIdx < tOffsetCount; ++tIdx)
                {
                    tOffset = tOffsetArray[tIdx];
                    int tLength = tOffset - tLastReplaceEnd;
                    if (tLength > 0)
                    {
                        Buffer.wstrcpy(pDest, pSrcA, tLength);
                        pDest += tLength;
                    }
                    Buffer.wstrcpy(pDest, pSrcB, tReplaceLenth);
                    tLastReplaceEnd = tOffset + tWordLength;
                    pDest += tReplaceLenth;
                }

                int tLeft = m_Length - tLastReplaceEnd;
                if (tLeft > 0)
                    Buffer.wstrcpy(pDest, pSrcA + tLastReplaceEnd, tLeft);

                *(pDest + tNewLength) = '\0';
                Assign(tResult, tNewLength, tNewLength + 1);
            }

            return this;
        }



        /// <summary>
        /// Fill number into a string
        /// </summary>
        /// <param name="_Value">The number of filling</param>
        public VString Fill(int _Value)
        {
            m_HashCode = 0;
            uint tValue = (uint)_Value;
            int tTotalLength = 0;
            bool tNegative = (_Value < 0);
            if (tNegative)
            {
                tValue = (uint)-_Value;
                tTotalLength = 1;
            }
            int tLength = X2StringUtil.GetIntLength(tValue);
            tTotalLength += tLength;
            Allocate(tTotalLength, m_AllocType);
            unsafe
            {
                char* pDest = buffer + tTotalLength;
                {
                    *(pDest--) = '\0';
                    for (int tIdx = 0; tIdx < tLength; tIdx++)
                    {
                        *(pDest--) = X2StringUtil.sNumerialChars[_Value % 10];
                        _Value = _Value / 10;
                    }
                    if(tNegative)
                        *pDest = '-';
                }
            }
            m_Length = tTotalLength;
            return this;
        }



        public VString Fill(uint _Value)
        {
            m_HashCode = 0;
            int tLength = X2StringUtil.GetIntLength(_Value);
            Allocate(tLength, m_AllocType);
            unsafe
            {
                char* pDest = buffer + tLength;
                {
                    *(pDest--) = '\0';
                    for (int tIdx = 0; tIdx < tLength; tIdx++)
                    {
                        *(pDest--) = X2StringUtil.sNumerialChars[_Value % 10];
                        _Value = _Value / 10;
                    }
                }
            }
            m_Length = tLength;
            return this;
        }



        /// <summary>
        /// Determines whether a specified string is a suffix of the the current instance.
        /// </summary>
        /// <param name="_Value">The string for </param>
        public bool EndsWith(VString _Value)
        {
            CheckValid();
            if (null == _Value)
                return false;
            if (object.ReferenceEquals(this, _Value))
                return true;
            int tVLength = _Value.Length;
            int tPrefixLength = m_Length - tVLength;
            if (tPrefixLength < 0)
                return false;

            unsafe
            {
                char* pSrc = buffer;
                char* pDest = _Value.buffer;
                {
                    char* pA = pSrc + tPrefixLength;
                    char* pB = pDest;
                    while (tVLength >= 12)
                    {
                        if (*(long*)pA != *(long*)pB)
                            return false;
                        if (*(long*)(pA + 4) != *(long*)(pB + 4))
                            return false;
                        if (*(long*)(pA + 8) != *(long*)(pB + 8))
                            return false;
                        pA += 12;
                        pB += 12;
                        tVLength -= 12;
                    }

                    while (tVLength > 0)
                    {
                        if (*(int*)pA != *(int*)pB)
                            break;
                        pA += 2;
                        pB += 2;
                        tVLength -= 2;
                    }
                    return (tVLength <= 0);
                }
            }
        }



        /// <summary>
        ///  Determines whether a specified string is a prefix of the the current instance.
        /// </summary>
        /// <param name="_Value"></param>
        public bool StartsWith(VString _Value)
        {
            CheckValid();
            if (object.ReferenceEquals(this, _Value))
                return true;
            int tVLength = _Value.Length;
            if (tVLength > m_Length)
                return false;

            unsafe
            {
                char* pSrc = buffer;
                char* pDest = _Value.buffer;
                {
                    char* pA = pSrc;
                    char* pB = pDest;
                    while (tVLength >= 12)
                    {
                        if (*(long*)pA != *(long*)pB)
                            return false;
                        if (*(long*)(pA + 4) != *(long*)(pB + 4))
                            return false;
                        if (*(long*)(pA + 8) != *(long*)(pB + 8))
                            return false;
                        pA += 12;
                        pB += 12;
                        tVLength -= 12;
                    }
                    while (tVLength > 0)
                    {
                        if (*(int*)pA != *(int*)pB)
                            break;
                        pA += 2;
                        pB += 2;
                        tVLength -= 2;
                    }
                    return (tVLength <= 0);
                }
            }
        }



        /// <summary>
        /// Remove a sub string from the current instance
        /// </summary>
        /// <param name="_Pos">The index of start</param>
        public unsafe VString Remove(int _Pos, bool _NoAlloc = true)
        {
            return Remove(_Pos, m_Length - _Pos, _NoAlloc);
        }



        /// <summary>
        /// Remove a sub string from the current instance
        /// </summary>
        /// <param name="_Pos">The index of start</param>
        /// <param name="_Count">The length of string</param>
        public unsafe VString Remove(int _Pos, int _Count, bool _NoAlloc = true)
        {
            CheckValid();
            if (_Pos < 0 || _Count < 0 || _Pos + _Count > m_Length)
                throw new ArgumentOutOfRangeException();
            char* pSrc = buffer;
            int tEnd = _Pos + _Count;
            if(_NoAlloc)
            {
                m_HashCode = 0;
                if (tEnd >= m_Length)
                    m_Length = _Pos;
                else
                {
                    //把剩余的内容复制到移除的内容处
                    Buffer.wstrcpy(pSrc + _Pos, pSrc + tEnd, m_Length - tEnd);
                    m_Length -= _Count;
                }
                *(pSrc + m_Length) = '\0';
                return this;
            }
            else
            {
                int tLength = m_Length - _Count;
                VString tResult = VStringPool.Instance.GetString(tLength, m_AllocType);
                char* pDest = tResult.buffer;
                if(_Pos > 0)
                    Buffer.wstrcpy(pDest, pSrc, _Pos);
                Buffer.wstrcpy(pDest + _Pos, pSrc + tEnd, m_Length - tEnd);
                *(pDest + tLength) = '\0';
                tResult.m_Length = tLength;
                return tResult;
            }
        }



        /// <summary>
        /// Gets the current string contains the 'value' string
        /// </summary>
        /// <param name="_Value">string for </param>
        /// <param name="_CaseSensitive">case sensitive</param>
        public bool Contains(VString _Value, bool _CaseSensitive = true)
        {
            return IndexOf(_Value, 0, m_Length, _CaseSensitive) >= 0;
        }



        /// <summary>
        /// Find a char from the current string
        /// </summary>
        /// <param name="_Char">char for</param>
        /// <param name="_CaseSensitive">case-sensitive</param>
        public int IndexOf(char _Char, bool _CaseSensitive = true)
        {
            CheckValid();
            unsafe
            {
                char* tSrc = buffer;
                if (_CaseSensitive)
                {
                    for (int tIdx = 0; tIdx < m_Length; ++tIdx)
                    {
                        if (tSrc[tIdx] == _Char)
                            return tIdx;
                    }
                }
                else
                {
                    _Char = X2StringUtil.ToLower(_Char);
                    for (int tIdx = 0; tIdx < m_Length; ++tIdx)
                    {
                        if (X2StringUtil.ToLower(tSrc[tIdx]) == _Char)
                            return tIdx;
                    }
                }
            }
            return -1;
        }



        /// <summary>
        ///  Find string from the current string
        /// </summary>
        /// <param name="_Value">string for</param>
        /// <param name="_StartIndex">the index of start</param>
        /// <param name="_CaseSensitive">case-sensitive</param>
        public int IndexOf(VString _Value, int _StartIndex = 0, bool _CaseSensitive = true)
        {
            return IndexOf(_Value, _StartIndex, _Value.Length, _CaseSensitive);
        }



        /// <summary>
        /// Find string from the current string
        /// </summary>
        /// <param name="_Value">string for</param>
        /// <param name="_StartIndex">the index of start</param>
        /// <param name="_Count">the count of string</param>
        /// <param name="_CaseSensitive">case-sensitive</param>
        /// <returns></returns>
        public int IndexOf(VString _Value, int _StartIndex, int _Count, bool _CaseSensitive = true)
        {
            CheckValid();
            if (null == _Value)
                return -1;

            int tVLength = _Value.Length;
            // Make sure we're not out of range
            if (_StartIndex < 0 || _StartIndex > m_Length || tVLength > _Count || tVLength > m_Length)
                return -1;

            if (_Count < 0 || _StartIndex > m_Length - _Count)
                return -1;

            if (m_Length == 0 && tVLength == 0)
                return 0;

            unsafe
            {
                char* pA = buffer + _StartIndex;
                char* pB = _Value.buffer;
                {
                    int tSubStrCount;
                    int tMaxIndex = m_Length - tVLength;
                    if (_CaseSensitive)
                    {
                        while (_StartIndex <= tMaxIndex)
                        {
                            char* pTmpA = pA;
                            char* pTmpB = pB;
                            tSubStrCount = 0;
                            if (*pTmpA == *pTmpB)
                            {
                                do
                                {
                                    pTmpA++;
                                    pTmpB++;
                                    tSubStrCount++;
                                    if (tSubStrCount == tVLength)
                                        return _StartIndex;

                                } while (*pTmpA == *pTmpB);
                            }
                            _StartIndex++;
                            pA++;
                        }
                    }
                    else
                    {
                        while (_StartIndex <= tMaxIndex)
                        {
                            char* pTmpA = pA;
                            char* pTmpB = pB;

                            if (X2StringUtil.ToLower(*pTmpA) == X2StringUtil.ToLower(*pTmpB))
                            {
                                tSubStrCount = 0;
                                do
                                {
                                    pTmpA++;
                                    pTmpB++;
                                    tSubStrCount++;
                                    if (tSubStrCount == _Count)
                                        return _StartIndex;

                                } while (X2StringUtil.ToLower(*pTmpA) == X2StringUtil.ToLower(*pTmpB));
                            }
                            _StartIndex++;
                            pA++;
                        }
                    }
                }
            }
            return -1;
        }



        /// <summary>
        /// Find a char from the current string
        /// </summary>
        /// <param name="_Char">char for</param>
        /// <param name="_CaseSensitive">case-sensitive</param>
        public int LastIndexOf(char _Char, bool _CaseSensitive = true)
        {
            CheckValid();
            unsafe
            {
                char* tSrc = buffer;
                if (_CaseSensitive)
                {
                    for (int tIdx = m_Length - 1; tIdx >= 0; --tIdx)
                    {
                        if (tSrc[tIdx] == _Char)
                            return tIdx;
                    }
                }
                else
                {
                    _Char = X2StringUtil.ToLower(_Char);
                    for (int tIdx = m_Length - 1; tIdx >= 0; --tIdx)
                    {
                        if (X2StringUtil.ToLower(tSrc[tIdx]) == _Char)
                            return tIdx;
                    }
                }
            }
            return -1;
        }



        public int LastIndexOf(string _Value, bool _CaseSensitive = true)
        {
            return LastIndexOf(_Value, Length > 0 ? (Length - 1) : 0, Length, _CaseSensitive);
        }



        public int LastIndexOf(string _Value, int _StartIndex, bool _CaseSensitive = true)
        {
            return LastIndexOf(_Value, _StartIndex, _StartIndex + 1, _CaseSensitive);
        }



        /// <summary>
        /// Find a char from the current string
        /// </summary>
        /// <param name="_Value">string for</param>
        /// <param name="_StartIndex">the index of start</param>
        /// <param name="_Count">the count of string backward</param>
        /// <param name="_CaseSensitive">case-sensitive</param>
        public int LastIndexOf(string _Value, int _StartIndex, int _Count, bool _CaseSensitive = true)
        {
            CheckValid();
            if (null == _Value)
                return -1;

            int tVLength = _Value.Length;

            if (m_Length == 0 && (_StartIndex == -1 || _StartIndex == 0))
            {
                if (tVLength != 0)
                    return -1;
                return 0;
            }

            if (_StartIndex > m_Length || _StartIndex < 0 || tVLength > _Count || tVLength > m_Length)
                return -1;

            if(_StartIndex == m_Length)
            {
                _StartIndex--;
                if (_Count > 0)
                    _Count--;
                if (tVLength == 0 && _Count >= 0 && _StartIndex + 1 >= _Count)
                    return _StartIndex;
            }

            if (_Count < 0 || _StartIndex + 1 < _Count)
                return -1;

            unsafe
            {
                char* pSrc = buffer;
                {
                    int tMaxIndex = tVLength - 1;
                    if (_CaseSensitive)
                    {
                        while (_StartIndex >= tMaxIndex)
                        {
                            int tSrcIdx = _StartIndex;
                            int tVIdx = tMaxIndex;
                            int tEqualCount = 0;
                            while (tEqualCount < tVLength && pSrc[tSrcIdx] == _Value[tVIdx])
                            {
                                tSrcIdx--;
                                tVIdx--;
                                tEqualCount++;
                            }
                            if (tEqualCount == tVLength)
                                return tSrcIdx + 1;

                            _StartIndex--;
                        }
                    }
                    else
                    {
                        while (_StartIndex >= tMaxIndex)
                        {
                            int tSrcIdx = _StartIndex;
                            int tVIdx = tMaxIndex;
                            int tEqualCount = 0;
                            while (tEqualCount < tVLength && X2StringUtil.ToLower(pSrc[tSrcIdx]) == X2StringUtil.ToLower(_Value[tVIdx]))
                            {
                                tSrcIdx--;
                                tVIdx--;
                                tEqualCount++;
                            }
                            if (tEqualCount == tVLength)
                                return tSrcIdx + 1;

                            _StartIndex--;
                        }
                    }
                }
            }
            return -1;
        }



        /// <summary>
        /// Remove the white char from the end and start of string
        /// </summary>
        public VString Trim(bool _NoAlloc = true)
        {
            return TrimInternal(TrimType.Both, _NoAlloc);
        }



        /// <summary>
        /// Remove the white char from  the start of string
        /// </summary>
        public VString TrimStart(bool _NoAlloc = true)
        {
            return TrimInternal(TrimType.Head, _NoAlloc);
        }



        /// <summary>
        /// Remove the white char from  the end of string
        /// </summary>
        public VString TrimEnd(bool _NoAlloc = true)
        {
            return TrimInternal(TrimType.Tail, _NoAlloc);
        }



        /// <summary>
        /// Remove the white char from  the string
        /// </summary>
        private VString TrimInternal(TrimType _Type, bool _NoAlloc = true)
        {
            CheckValid();
            int tStart = 0;
            int tEnd = m_Length - 1;
            //Trim specified characters.
            unsafe
            {
                char* pStr = buffer;
                if (_Type != TrimType.Tail)
                {
                    for (; tStart < m_Length; tStart++)
                    {
                        if (*pStr != ' ')
                            break;
                        pStr++;
                    }
                }

                if (_Type != TrimType.Head)
                {
                    pStr = buffer + tEnd;
                    for (; tEnd >= tStart; tEnd--)
                    {
                        if (*pStr != ' ')
                            break;
                        pStr--;
                    }
                }
            }

            return Substring(tStart, tEnd - tStart + 1, _NoAlloc);
        }



        /// <summary>
        /// Clone the current string
        /// </summary>
        [System.Security.SecuritySafeCritical]
        unsafe public VString Clone()
        {
            CheckValid();
            VString tResult = VStringPool.Instance.GetString(m_Length, m_AllocType);
            char* pDest = tResult.buffer;
            char* pSrc = buffer;
            Buffer.wstrcpy(pDest, pSrc, m_Length);
            *(pDest + m_Length) = '\0';
            tResult.m_Length = m_Length;
            return tResult;
        }



        /// <summary>
        /// Concat two XString
        /// </summary>
        public static VString operator +(VString _Arg0, VString _Arg1)
        {
            return VString.Concat(_Arg0, _Arg1);
        }



        /// <summary>
        /// a and b are equals?
        /// </summary>
        public static bool operator ==(VString _A, VString _B)
        {
            return Equals(_A, _B);
        }



        /// <summary>
        /// arg0 and arg1 are equals?
        /// </summary>
        public static bool operator !=(VString _Arg0, VString _Arg1)
        {
            return !Equals(_Arg0, _Arg1);
        }



        /// <summary>
        /// String are equals?
        /// </summary>
        public override bool Equals(object _Value)
        {
            return Equals(this, _Value as VString);
        }



        /// <summary>
        /// String are equals?
        /// </summary>
        public static bool Equals(VString _StrA, VString _StrB)
        {
            if (object.ReferenceEquals(_StrA, _StrB))
                return true;

            if ((object)_StrA == null || (object)_StrB == null)
                return false;

            if (_StrA.Length != _StrB.Length)
                return false;

            if (_StrA.HashCode != 0 && _StrB.HashCode != 0)
                return _StrA.HashCode == _StrB.HashCode;
            return EqualsHelper(_StrA, _StrB);
        }



        /// <summary>
        /// String are equals?
        /// </summary>
        private unsafe static bool EqualsHelper(VString _StrA, VString _StrB)
        {
            int tLength = _StrA.Length;
            unsafe
            {
                char* pSrcA = _StrA.buffer;
                char* pSrcB = _StrB.buffer;
                if (pSrcA == null || pSrcB == null)
                    return false;
                {
                    char* pA = pSrcA;
                    char* pB = pSrcB;
                    while (tLength >= 12)
                    {
                        if (*(long*)pA != *(long*)pB)
                            return false;
                        if (*(long*)(pA + 4) != *(long*)(pB + 4))
                            return false;
                        if (*(long*)(pA + 8) != *(long*)(pB + 8))
                            return false;

                        pA += 12;
                        pB += 12;
                        tLength -= 12;
                    }

                    //奇数时用结束符凑成偶数，偶数时不考虑结束符
                    while (tLength > 0)
                    {
                        if (*(int*)pA != *(int*)pB)
                            break;
                        pA += 2;
                        pB += 2;
                        tLength -= 2;
                    }
                }
            }

            return (tLength <= 0);
        }



        /// <summary>
        /// Gets the hash code of string
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            if (inStringPool)
                return base.GetHashCode();
            if (m_HashCode != 0)
                return m_HashCode;
            unsafe
            {
                if (0 == m_MemBuffer)
                    return 0;
                char* pSrc = buffer;
                {
#if WIN32
                    int tHash1 = (5381<<16) + 5381;
#else
                    int tHash1 = 5381;
#endif
                    int tHash2 = tHash1;

#if WIN32
                     // 32 bit machines.
                    int* pInt = (int *)pSrc;
                    int tLength = m_Length;
                    while (tLength > 2)
                    {
                        tHash1 = ((tHash1 << 5) + tHash1 + (tHash1 >> 27)) ^ pInt[0];
                        tHash2 = ((tHash2 << 5) + tHash2 + (tHash2 >> 27)) ^ pInt[1];
                        pInt += 2;
                        tLength  -= 4;
                    }

                    if (tLength > 0)
                        tHash1 = ((tHash1 << 5) + tHash1 + (tHash1 >> 27)) ^ pInt[0];
#else
                    int tChar;
                    char* pChar = pSrc;
                    while ((tChar = pChar[0]) != 0)
                    {
                        tHash1 = ((tHash1 << 5) + tHash1) ^ tChar;
                        tChar = pChar[1];
                        if (tChar == 0)
                            break;
                        tHash2 = ((tHash2 << 5) + tHash2) ^ tChar;
                        pChar += 2;
                    }
#endif
                    m_HashCode = tHash1 + (tHash2 * 1566083941);
                    return m_HashCode;
                }
            }
        }
    }
}
#endif