/// <summary>
        /// Create a deep copy.
        /// </summary>
        public virtual object Clone()
        {
            VariantDictionary vdNew = new VariantDictionary();

            foreach (KeyValuePair <string, object> kvp in m_d)
            {
                object o = kvp.Value;
                if (o == null)
                {
                    Debug.Assert(false); continue;
                }

                Type t = o.GetType();
                if (t == typeof(byte[]))
                {
                    byte[] p    = (byte[])o;
                    byte[] pNew = new byte[p.Length];
                    if (p.Length > 0)
                    {
                        Array.Copy(p, pNew, p.Length);
                    }

                    o = pNew;
                }

                vdNew.m_d[kvp.Key] = o;
            }

            return(vdNew);
        }
        public void CopyTo(VariantDictionary d)
        {
            if (d == null)
            {
                Debug.Assert(false); return;
            }

            // Do not clear the target
            foreach (KeyValuePair <string, object> kvp in m_d)
            {
                d.m_d[kvp.Key] = kvp.Value;
            }
        }
        public static VariantDictionary Deserialize(byte[] pb)
        {
            if (pb == null)
            {
                Debug.Assert(false); return(null);
            }

            VariantDictionary d = new VariantDictionary();

            using (MemoryStream ms = new MemoryStream(pb, false))
            {
                ushort uVersion = MemUtil.BytesToUInt16(MemUtil.Read(ms, 2));
                if ((uVersion & VdmCritical) > (VdVersion & VdmCritical))
                {
                    throw new FormatException(KLRes.FileNewVerReq);
                }

                while (true)
                {
                    int iType = ms.ReadByte();
                    if (iType < 0)
                    {
                        throw new EndOfStreamException(KLRes.FileCorrupted);
                    }
                    byte btType = (byte)iType;
                    if (btType == (byte)VdType.None)
                    {
                        break;
                    }

                    int    cbName = MemUtil.BytesToInt32(MemUtil.Read(ms, 4));
                    byte[] pbName = MemUtil.Read(ms, cbName);
                    if (pbName.Length != cbName)
                    {
                        throw new EndOfStreamException(KLRes.FileCorrupted);
                    }
                    string strName = StrUtil.Utf8.GetString(pbName, 0, pbName.Length);

                    int    cbValue = MemUtil.BytesToInt32(MemUtil.Read(ms, 4));
                    byte[] pbValue = MemUtil.Read(ms, cbValue);
                    if (pbValue.Length != cbValue)
                    {
                        throw new EndOfStreamException(KLRes.FileCorrupted);
                    }

                    switch (btType)
                    {
                    case (byte)VdType.UInt32:
                        if (cbValue == 4)
                        {
                            d.SetUInt32(strName, MemUtil.BytesToUInt32(pbValue));
                        }
                        else
                        {
                            Debug.Assert(false);
                        }
                        break;

                    case (byte)VdType.UInt64:
                        if (cbValue == 8)
                        {
                            d.SetUInt64(strName, MemUtil.BytesToUInt64(pbValue));
                        }
                        else
                        {
                            Debug.Assert(false);
                        }
                        break;

                    case (byte)VdType.Bool:
                        if (cbValue == 1)
                        {
                            d.SetBool(strName, (pbValue[0] != 0));
                        }
                        else
                        {
                            Debug.Assert(false);
                        }
                        break;

                    case (byte)VdType.Int32:
                        if (cbValue == 4)
                        {
                            d.SetInt32(strName, MemUtil.BytesToInt32(pbValue));
                        }
                        else
                        {
                            Debug.Assert(false);
                        }
                        break;

                    case (byte)VdType.Int64:
                        if (cbValue == 8)
                        {
                            d.SetInt64(strName, MemUtil.BytesToInt64(pbValue));
                        }
                        else
                        {
                            Debug.Assert(false);
                        }
                        break;

                    case (byte)VdType.String:
                        d.SetString(strName, StrUtil.Utf8.GetString(pbValue, 0, pbValue.Length));
                        break;

                    case (byte)VdType.ByteArray:
                        d.SetByteArray(strName, pbValue);
                        break;

                    default:
                        Debug.Assert(false);                                 // Unknown type
                        break;
                    }
                }

                Debug.Assert(ms.ReadByte() < 0);
            }

            return(d);
        }
        public static byte[] Serialize(VariantDictionary p)
        {
            if (p == null)
            {
                Debug.Assert(false); return(null);
            }

            byte[] pbRet;
            using (MemoryStream ms = new MemoryStream())
            {
                MemUtil.Write(ms, MemUtil.UInt16ToBytes(VdVersion));

                foreach (KeyValuePair <string, object> kvp in p.m_d)
                {
                    string strName = kvp.Key;
                    if (string.IsNullOrEmpty(strName))
                    {
                        Debug.Assert(false); continue;
                    }
                    byte[] pbName = StrUtil.Utf8.GetBytes(strName);

                    object o = kvp.Value;
                    if (o == null)
                    {
                        Debug.Assert(false); continue;
                    }

                    Type   t       = o.GetType();
                    VdType vt      = VdType.None;
                    byte[] pbValue = null;
                    if (t == typeof(uint))
                    {
                        vt      = VdType.UInt32;
                        pbValue = MemUtil.UInt32ToBytes((uint)o);
                    }
                    else if (t == typeof(ulong))
                    {
                        vt      = VdType.UInt64;
                        pbValue = MemUtil.UInt64ToBytes((ulong)o);
                    }
                    else if (t == typeof(bool))
                    {
                        vt         = VdType.Bool;
                        pbValue    = new byte[1];
                        pbValue[0] = ((bool)o ? (byte)1 : (byte)0);
                    }
                    else if (t == typeof(int))
                    {
                        vt      = VdType.Int32;
                        pbValue = MemUtil.Int32ToBytes((int)o);
                    }
                    else if (t == typeof(long))
                    {
                        vt      = VdType.Int64;
                        pbValue = MemUtil.Int64ToBytes((long)o);
                    }
                    else if (t == typeof(string))
                    {
                        vt      = VdType.String;
                        pbValue = StrUtil.Utf8.GetBytes((string)o);
                    }
                    else if (t == typeof(byte[]))
                    {
                        vt      = VdType.ByteArray;
                        pbValue = (byte[])o;
                    }
                    else
                    {
                        Debug.Assert(false); continue;
                    }                                                           // Unknown type

                    ms.WriteByte((byte)vt);
                    MemUtil.Write(ms, MemUtil.Int32ToBytes(pbName.Length));
                    MemUtil.Write(ms, pbName);
                    MemUtil.Write(ms, MemUtil.Int32ToBytes(pbValue.Length));
                    MemUtil.Write(ms, pbValue);
                }

                ms.WriteByte((byte)VdType.None);
                pbRet = ms.ToArray();
            }

            return(pbRet);
        }