Пример #1
0
        // TODO: Decode native nvlist
        static bool DecodeNvList(byte[] nvlist, out Dictionary <string, NVS_Item> decodedNvList, bool xdr,
                                 bool littleEndian)
        {
            decodedNvList = new Dictionary <string, NVS_Item>();

            if (nvlist == null || nvlist.Length < 16)
            {
                return(false);
            }

            if (!xdr)
            {
                return(false);
            }

            int offset = 8;

            while (offset < nvlist.Length)
            {
                NVS_Item item    = new NVS_Item();
                int      currOff = offset;

                item.encodedSize = BigEndianBitConverter.ToUInt32(nvlist, offset);

                // Finished
                if (item.encodedSize == 0)
                {
                    break;
                }

                offset          += 4;
                item.decodedSize = BigEndianBitConverter.ToUInt32(nvlist, offset);
                offset          += 4;
                uint nameLength = BigEndianBitConverter.ToUInt32(nvlist, offset);
                offset += 4;
                if (nameLength % 4 > 0)
                {
                    nameLength += 4 - nameLength % 4;
                }
                byte[] nameBytes = new byte[nameLength];
                Array.Copy(nvlist, offset, nameBytes, 0, nameLength);
                item.name     = StringHandlers.CToString(nameBytes);
                offset       += (int)nameLength;
                item.dataType = (NVS_DataTypes)BigEndianBitConverter.ToUInt32(nvlist, offset);
                offset       += 4;
                item.elements = BigEndianBitConverter.ToUInt32(nvlist, offset);
                offset       += 4;

                if (item.elements == 0)
                {
                    decodedNvList.Add(item.name, item);
                    continue;
                }

                switch (item.dataType)
                {
                case NVS_DataTypes.DATA_TYPE_BOOLEAN:
                case NVS_DataTypes.DATA_TYPE_BOOLEAN_ARRAY:
                case NVS_DataTypes.DATA_TYPE_BOOLEAN_VALUE:
                    if (item.elements > 1)
                    {
                        bool[] boolArray = new bool[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            uint temp = BigEndianBitConverter.ToUInt32(nvlist, offset);
                            boolArray[i] = temp > 0;
                            offset      += 4;
                        }

                        item.value = boolArray;
                    }
                    else
                    {
                        uint temp = BigEndianBitConverter.ToUInt32(nvlist, offset);
                        item.value = temp > 0;
                        offset    += 4;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_BYTE:
                case NVS_DataTypes.DATA_TYPE_BYTE_ARRAY:
                case NVS_DataTypes.DATA_TYPE_UINT8:
                case NVS_DataTypes.DATA_TYPE_UINT8_ARRAY:
                    if (item.elements > 1)
                    {
                        byte[] byteArray = new byte[item.elements];
                        Array.Copy(nvlist, offset, byteArray, 0, item.elements);
                        offset += (int)item.elements;
                        if (item.elements % 4 > 0)
                        {
                            offset += 4 - (int)(item.elements % 4);
                        }
                        item.value = byteArray;
                    }
                    else
                    {
                        item.value = nvlist[offset];
                        offset    += 4;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_DOUBLE:
                    if (item.elements > 1)
                    {
                        double[] doubleArray = new double[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            double temp = BigEndianBitConverter.ToDouble(nvlist, offset);
                            doubleArray[i] = temp;
                            offset        += 8;
                        }

                        item.value = doubleArray;
                    }
                    else
                    {
                        item.value = BigEndianBitConverter.ToDouble(nvlist, offset);
                        offset    += 8;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_HRTIME:
                    if (item.elements > 1)
                    {
                        DateTime[] hrtimeArray = new DateTime[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            DateTime temp =
                                DateHandlers.UnixHrTimeToDateTime(BigEndianBitConverter.ToUInt64(nvlist, offset));
                            hrtimeArray[i] = temp;
                            offset        += 8;
                        }

                        item.value = hrtimeArray;
                    }
                    else
                    {
                        item.value =
                            DateHandlers.UnixHrTimeToDateTime(BigEndianBitConverter.ToUInt64(nvlist, offset));
                        offset += 8;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_INT16:
                case NVS_DataTypes.DATA_TYPE_INT16_ARRAY:
                    if (item.elements > 1)
                    {
                        short[] shortArray = new short[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            short temp = BigEndianBitConverter.ToInt16(nvlist, offset);
                            shortArray[i] = temp;
                            offset       += 4;
                        }

                        item.value = shortArray;
                    }
                    else
                    {
                        item.value = BigEndianBitConverter.ToInt16(nvlist, offset);
                        offset    += 4;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_INT32:
                case NVS_DataTypes.DATA_TYPE_INT32_ARRAY:
                    if (item.elements > 1)
                    {
                        int[] intArray = new int[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            int temp = BigEndianBitConverter.ToInt32(nvlist, offset);
                            intArray[i] = temp;
                            offset     += 4;
                        }

                        item.value = intArray;
                    }
                    else
                    {
                        item.value = BigEndianBitConverter.ToInt32(nvlist, offset);
                        offset    += 4;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_INT64:
                case NVS_DataTypes.DATA_TYPE_INT64_ARRAY:
                    if (item.elements > 1)
                    {
                        long[] longArray = new long[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            long temp = BigEndianBitConverter.ToInt64(nvlist, offset);
                            longArray[i] = temp;
                            offset      += 8;
                        }

                        item.value = longArray;
                    }
                    else
                    {
                        item.value = BigEndianBitConverter.ToInt64(nvlist, offset);
                        offset    += 8;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_INT8:
                case NVS_DataTypes.DATA_TYPE_INT8_ARRAY:
                    if (item.elements > 1)
                    {
                        sbyte[] sbyteArray = new sbyte[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            sbyte temp = (sbyte)nvlist[offset];
                            sbyteArray[i] = temp;
                            offset++;
                        }

                        item.value = sbyteArray;
                        if (sbyteArray.Length % 4 > 0)
                        {
                            offset += 4 - sbyteArray.Length % 4;
                        }
                    }
                    else
                    {
                        item.value = BigEndianBitConverter.ToInt64(nvlist, offset);
                        offset    += 4;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_STRING:
                case NVS_DataTypes.DATA_TYPE_STRING_ARRAY:
                    if (item.elements > 1)
                    {
                        string[] stringArray = new string[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            uint strLength = BigEndianBitConverter.ToUInt32(nvlist, offset);
                            offset += 4;
                            byte[] strBytes = new byte[strLength];
                            Array.Copy(nvlist, offset, strBytes, 0, strLength);
                            stringArray[i] = StringHandlers.CToString(strBytes);
                            offset        += (int)strLength;
                            if (strLength % 4 > 0)
                            {
                                offset += 4 - (int)(strLength % 4);
                            }
                        }

                        item.value = stringArray;
                    }
                    else
                    {
                        uint strLength = BigEndianBitConverter.ToUInt32(nvlist, offset);
                        offset += 4;
                        byte[] strBytes = new byte[strLength];
                        Array.Copy(nvlist, offset, strBytes, 0, strLength);
                        item.value = StringHandlers.CToString(strBytes);
                        offset    += (int)strLength;
                        if (strLength % 4 > 0)
                        {
                            offset += 4 - (int)(strLength % 4);
                        }
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_UINT16:
                case NVS_DataTypes.DATA_TYPE_UINT16_ARRAY:
                    if (item.elements > 1)
                    {
                        ushort[] ushortArray = new ushort[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            ushort temp = BigEndianBitConverter.ToUInt16(nvlist, offset);
                            ushortArray[i] = temp;
                            offset        += 4;
                        }

                        item.value = ushortArray;
                    }
                    else
                    {
                        item.value = BigEndianBitConverter.ToUInt16(nvlist, offset);
                        offset    += 4;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_UINT32:
                case NVS_DataTypes.DATA_TYPE_UINT32_ARRAY:
                    if (item.elements > 1)
                    {
                        uint[] uintArray = new uint[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            uint temp = BigEndianBitConverter.ToUInt32(nvlist, offset);
                            uintArray[i] = temp;
                            offset      += 4;
                        }

                        item.value = uintArray;
                    }
                    else
                    {
                        item.value = BigEndianBitConverter.ToUInt32(nvlist, offset);
                        offset    += 4;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_UINT64:
                case NVS_DataTypes.DATA_TYPE_UINT64_ARRAY:
                    if (item.elements > 1)
                    {
                        ulong[] ulongArray = new ulong[item.elements];
                        for (int i = 0; i < item.elements; i++)
                        {
                            ulong temp = BigEndianBitConverter.ToUInt64(nvlist, offset);
                            ulongArray[i] = temp;
                            offset       += 8;
                        }

                        item.value = ulongArray;
                    }
                    else
                    {
                        item.value = BigEndianBitConverter.ToUInt64(nvlist, offset);
                        offset    += 8;
                    }

                    break;

                case NVS_DataTypes.DATA_TYPE_NVLIST:
                    if (item.elements > 1)
                    {
                        goto default;
                    }

                    byte[] subListBytes = new byte[item.encodedSize - (offset - currOff)];
                    Array.Copy(nvlist, offset, subListBytes, 0, subListBytes.Length);
                    if (DecodeNvList(subListBytes, out Dictionary <string, NVS_Item> subList, true, littleEndian))
                    {
                        item.value = subList;
                    }
                    else
                    {
                        goto default;
                    }
                    offset = (int)(currOff + item.encodedSize);
                    break;

                default:
                    byte[] unknown = new byte[item.encodedSize - (offset - currOff)];
                    Array.Copy(nvlist, offset, unknown, 0, unknown.Length);
                    item.value = unknown;
                    offset     = (int)(currOff + item.encodedSize);
                    break;
                }

                decodedNvList.Add(item.name, item);
            }

            return(decodedNvList.Count > 0);
        }