예제 #1
0
        public static MsgPackItem Unpack(Stream stream, bool dynamicallyCompact = true, bool preservePackages = false, bool continueProcessingOnBreakingError = false, bool readUntilEof = false)
        {
            var settings = new MsgPackSettings()
            {
                DynamicallyCompact = dynamicallyCompact,
                PreservePackages   = preservePackages,
                ContinueProcessingOnBreakingError = continueProcessingOnBreakingError
            };

            if (!readUntilEof)
            {
                return(Unpack(stream, settings));
            }

            var item = Unpack(stream, settings);

            if (stream.Position == stream.Length)
            {
                return(item);
            }
            var items = new List <MsgPackItem>();

            items.Add(item);
            do
            {
                items.Add(Unpack(stream, settings));
            } while (stream.Position < stream.Length);
            return(new MpArray(settings, items));
        }
예제 #2
0
 internal MpError(MsgPackSettings settings, MsgPackItem partialItemWithNestedError) : this(settings, partialItemWithNestedError.StoredOffset, partialItemWithNestedError.TypeId,
                                                                                           string.Concat("A nested item contains an error. ", settings.ContinueProcessingOnBreakingError
 ? "Inspect the PartialItem to view the part of the message that could be read. Since the option 'ContinueProcessingOnBreakingError' is used, the 'IsBestGuess' property of each subitem will indicate if it was read before or after the error."
 : "Inspect the PartialItem to view the part of the message that could be read."))
 {
     PartialItem = partialItemWithNestedError;
 }
예제 #3
0
        protected static byte[] SwapIfLittleEndian(MsgPackSettings settings, byte[] bytes, int start, int count)
        {
            byte[] final = new byte[count];
            int    last  = count - 1;

            if (!SwapEndianChoice(settings, count))
            {
                int offset = start + last;
                for (int t = last; t >= 0; t--)
                {
                    final[t] = bytes[offset];
                    offset--;
                }
                return(final);
            }

            int c = start;

            for (int t = last; t >= 0; t--)
            {
                final[t] = bytes[c];
                c++;
            }

            return(final);
        }
예제 #4
0
        public static MsgPackItem SerializeObject(object item, MsgPackSettings settings)
        {
            if (ReferenceEquals(item, null))
            {
                return(new MpNull());
            }
            Type tType = item.GetType();

            if (MsgPackSerializer.NativelySupportedTypes.Contains(tType))
            {
                return(MsgPackItem.Pack(item, settings));
                // Maybe we should rather throw an exception here
            }
            PropertyInfo[] props = GetSerializedProps(tType);
            Dictionary <string, object> propVals = new Dictionary <string, object>(props.Length);

            for (int t = props.Length - 1; t >= 0; t--)
            {
                propVals.Add(props[t].Name, props[t].GetValue(item, null));
            }
            return(new MpMap(settings)
            {
                Value = propVals
            });
        }
예제 #5
0
        private static byte[] ToFExt4Bytes(MsgPackSettings settings, DateTime dt)
        {
            long seconds = DateTimeToEpoch(dt);
            uint sec     = (uint)seconds;

            return(SwapIfLittleEndian(settings, BitConverter.GetBytes(sec)));
        }
예제 #6
0
 public MpMap(KeyValuePair <object, object>[] val, bool dynamicallyCompact = true) : this()
 {
     _settings = new MsgPackSettings()
     {
         _dynamicallyCompact = dynamicallyCompact
     };
     value = val;
 }
예제 #7
0
        public static void Serialize <T>(T item, Stream target, MsgPackSettings settings)
        {
            MsgPackItem packed = SerializeObject(item, settings);

            byte[] buffer = packed.ToBytes();
            target.Write(buffer, 0, buffer.Length);
            return;
        }
예제 #8
0
 public MpArray(MsgPackSettings settings, List <MsgPackItem> initialPackedItems) : base(settings)
 {
     packedItems = initialPackedItems.ToArray();
     value       = new object[packedItems.Length];
     for (var i = 0; i < packedItems.Length; i++)
     {
         value[i] = packedItems[i].Value;
     }
 }
예제 #9
0
        private static MpDateTime ToExt8(MsgPackSettings settings, DateTime dt)
        {
            MpDateTime mpdt = new MpDateTime()
            {
                BaseValue = ToExt8Bytes(settings, dt),
                Value     = dt
            };

            return(mpdt);
        }
예제 #10
0
        public static MpRoot PackMultiple(MsgPackSettings settings, IEnumerable values)
        {
            MpRoot root = new MpRoot(settings);

            foreach (object item in values)
            {
                root.Add(Pack(item, settings));
            }
            return(root);
        }
예제 #11
0
        public static MpRoot PackMultiple(MsgPackSettings settings, params object[] values)
        {
            MpRoot root = new MpRoot(settings, values.Length);

            for (int t = 0; t < values.Length; t++)
            {
                root.Add(Pack(values[t], settings));
            }
            return(root);
        }
예제 #12
0
        public static DateTime ConvertExt(MsgPackSettings settings, MpExt ext)
        {
            if (ext.TypeSpecifier != -1)
            {
                throw new MsgPackException(string.Concat("The extension type ", ext.TypeSpecifier, " is not a recognised DatTime or TimeStamp, expected type -1."), ext.StoredOffset + 1, ext.TypeId);
            }

            switch (ext.TypeId)
            {
            case MsgPackTypeId.MpFExt4:
                uint seconds = BitConverter.ToUInt32(SwapIfLittleEndian(settings, (byte[])ext.Value), 0);
                return(EpochToLocalDateTime(seconds));

            case MsgPackTypeId.MpFExt8:
                byte[] bitVal = (byte[])ext.Value;

                if (BitConverter.IsLittleEndian)
                {
                    SwapIfLittleEndian(settings, bitVal, 0, 4);
                    SwapIfLittleEndian(settings, bitVal, 4, 4);
                }

                ulong bytes = BitConverter.ToUInt64(bitVal, 0);
                ulong nanoSecc;
                ulong sec;
                long  ticks;
                unchecked {
                    nanoSecc = bytes >> 34;
                    ulong mask = 0x3FFFFFFFF;
                    sec   = (bytes & mask);
                    ticks = (long)nanoSecc / 100;
                }

                DateTime ret = Zero.AddSeconds(sec).Add(new TimeSpan(ticks));
                return(ret.ToLocalTime());

            case MsgPackTypeId.MpExt8:
                byte[]   vall    = (byte[])ext.Value;
                uint     nanoSec = BitConverter.ToUInt32(SwapIfLittleEndian(settings, vall, 0, 4), 0);
                long     sc      = BitConverter.ToInt64(SwapIfLittleEndian(settings, vall, 4, 8), 0);
                long     tick    = nanoSec / 100;
                TimeSpan subSec  = TimeSpan.FromTicks(tick);
                if (sc < 0)
                {
                    return(EpochToLocalDateTime(sc) - subSec);
                }
                else
                {
                    return(EpochToLocalDateTime(sc) + subSec);
                }
            }

            throw new MsgPackException(string.Concat("The extension type with base type ", GetOfficialTypeName(ext.TypeId), " is not recognised as a DatTime or TimeStamp. expected ", GetOfficialTypeName(MsgPackTypeId.MpFExt4), " or ", GetOfficialTypeName(MsgPackTypeId.MpFExt8), " or ", GetOfficialTypeName(MsgPackTypeId.MpExt8)), ext.StoredOffset, ext.TypeId);
        }
예제 #13
0
        public static byte[] Serialize <T>(T item, MsgPackSettings settings)
        {
            if (MsgPackSerializer.NativelySupportedTypes.Contains(typeof(T)))
            {
                return(MsgPackItem.Pack(item, settings).ToBytes());
            }
            MemoryStream ms = new MemoryStream();

            Serialize(item, ms, settings);
            return(ms.ToArray());
        }
예제 #14
0
        private static byte[] ToExt8Bytes(MsgPackSettings settings, DateTime dt)
        {
            long seconds         = DateTimeToEpoch(dt);
            long ticksFractional = (dt.Ticks % TimeSpan.TicksPerSecond);
            uint nanoSec         = (uint)ticksFractional * 100;

            byte[] bitVal = new byte[12];
            SwapIfLittleEndian(settings, BitConverter.GetBytes(nanoSec)).CopyTo(bitVal, 0);
            SwapIfLittleEndian(settings, BitConverter.GetBytes(seconds)).CopyTo(bitVal, 4);
            return(bitVal);
        }
예제 #15
0
 public static bool SwapEndianChoice(MsgPackSettings settings, int length)
 {
     if (settings.EndianAction == EndianAction.NeverSwap || length <= 1)
     {
         return(false);
     }
     if (settings.EndianAction == EndianAction.SwapIfCurrentSystemIsLittleEndian && !BitConverter.IsLittleEndian)
     {
         return(false);
     }
     return(true);
 }
예제 #16
0
        public static MpDateTime FromDateTime(MsgPackSettings settings, DateTime dt, bool preserveFractionalSeconds = true)
        {
            dt = dt.ToUniversalTime();

            if (dt < Zero || dt > MaxFExt8)
            {
                return(ToExt8(settings, dt)); // lartgest 15 bytes
            }
            if (dt > MaxFExt4 || (preserveFractionalSeconds && HasFractionalSeconds(dt)))
            {
                return(ToFExt8(settings, dt)); // 10 bytes
            }
            return(ToFExt4(settings, dt));     // 6 bytes
        }
예제 #17
0
        private static byte[] ToBaseValue(MsgPackSettings settings, DateTime dt, bool preserveFractionalSeconds = true)
        {
            dt = dt.ToUniversalTime();

            if (dt < Zero || dt > MaxFExt8)
            {
                return(ToExt8Bytes(settings, dt)); // lartgest 15 bytes
            }
            if (dt > MaxFExt4 || (preserveFractionalSeconds && HasFractionalSeconds(dt)))
            {
                return(ToFExt8Bytes(settings, dt)); // 10 bytes
            }
            return(ToFExt4Bytes(settings, dt));     // 6 bytes
        }
예제 #18
0
        protected static void ReorderIfLittleEndian(MsgPackSettings settings, List <byte> bytes)
        {
            if (!SwapEndianChoice(settings, bytes.Count))
            {
                return;
            }
            byte[] swapped = new byte[bytes.Count];
            int    c       = 0;

            for (int t = swapped.Length - 1; t >= 0; t--)
            {
                swapped[t] = bytes[c];
                c++;
            }
            bytes.Clear();
            bytes.AddRange(swapped);
        }
예제 #19
0
        private static byte[] ToFExt8Bytes(MsgPackSettings settings, DateTime dt)
        {
            ulong seconds         = (ulong)DateTimeToEpoch(dt);
            long  ticksFractional = (dt.Ticks % TimeSpan.TicksPerSecond);
            ulong nanoSec         = (ulong)ticksFractional * 100;

            ulong prepareBytes = nanoSec << 34;

            prepareBytes = prepareBytes | seconds;
            byte[] bitVal = BitConverter.GetBytes(prepareBytes);
            if (BitConverter.IsLittleEndian)
            {
                SwapIfLittleEndian(settings, bitVal, 0, 4);
                SwapIfLittleEndian(settings, bitVal, 4, 4);
            }
            return(bitVal);
        }
예제 #20
0
        protected static byte[] SwapIfLittleEndian(MsgPackSettings settings, byte[] bytes)
        {
            if (!SwapEndianChoice(settings, bytes.Length))
            {
                return(bytes);
            }

            byte[] final = new byte[bytes.Length];
            int    c     = 0;

            for (int t = final.Length - 1; t >= 0; t--)
            {
                final[t] = bytes[c];
                c++;
            }

            return(final);
        }
예제 #21
0
        protected static void ReorderIfLittleEndian(MsgPackSettings settings, byte[] bytes)
        {
            if (!SwapEndianChoice(settings, bytes.Length))
            {
                return;
            }

            byte[] swapped = new byte[bytes.Length];
            int    c       = 0;

            for (int t = swapped.Length - 1; t >= 0; t--)
            {
                swapped[t] = bytes[c];
                c++;
            }
            for (int t = bytes.Length - 1; t >= 0; t--)
            {
                bytes[t] = swapped[t];
            }
        }
예제 #22
0
        public static MpRoot UnpackMultiple(Stream stream, MsgPackSettings settings)
        {
            MpRoot items = new MpRoot(settings)
            {
                storedOffset = stream.Position
            };
            long len     = stream.Length - 1;
            long lastpos = stream.Position;

            while (stream.Position < len)
            {
                try {
                    items.Add(Unpack(stream, settings));
                    lastpos = stream.Position;
                } catch (Exception ex) {
                    items.Add(new MpError(settings, ex, "Offset after parsing error is ", stream.Position)
                    {
                        storedOffset = lastpos, storedLength = stream.Position - lastpos
                    });
                    if (settings.ContinueProcessingOnBreakingError)
                    {
                        if (lastpos == stream.Position && stream.Position < len)
                        {
                            FindNextValidTypeId(stream);
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }

            items.storedLength = stream.Position - items.storedOffset;
            return(items);
        }
예제 #23
0
 public MpFloat(MsgPackSettings settings) : base(settings)
 {
 }
예제 #24
0
 public MpArray(MsgPackSettings settings) : base(settings)
 {
 }
예제 #25
0
        public static MsgPackItem Unpack(Stream stream, MsgPackSettings settings)
        {
            int typeByte = stream.ReadByte();

            if (typeByte < 0)
            {
                return(new MpError(settings, stream.Position, MsgPackTypeId.NeverUsed, "Unexpected end of data."));
            }
            MsgPackItem item = null;

            try {
                MsgPackTypeId type = (MsgPackTypeId)typeByte;
                switch (type)
                {
                case MsgPackTypeId.MpNull: item = new MpNull(settings); break;

                case MsgPackTypeId.MpBoolFalse:
                case MsgPackTypeId.MpBoolTrue: item = new MpBool(settings); break;

                //case MsgPackTypes.MpBytePart:
                //case MsgPackTypes.MpSBytePart:
                case MsgPackTypeId.MpSByte:
                case MsgPackTypeId.MpShort:
                case MsgPackTypeId.MpInt:
                case MsgPackTypeId.MpLong:
                case MsgPackTypeId.MpUByte:
                case MsgPackTypeId.MpUShort:
                case MsgPackTypeId.MpUInt:
                case MsgPackTypeId.MpULong: item = new MpInt(settings); break;

                case MsgPackTypeId.MpFloat:
                case MsgPackTypeId.MpDouble: item = new MpFloat(settings); break;

                //case MsgPackTypeId.MpStr5:
                case MsgPackTypeId.MpStr8:
                case MsgPackTypeId.MpStr16:
                case MsgPackTypeId.MpStr32: item = new MpString(settings); break;

                case MsgPackTypeId.MpBin8:
                case MsgPackTypeId.MpBin16:
                case MsgPackTypeId.MpBin32: item = new MpBin(settings); break;

                //case MsgPackTypeId.MpArray4:
                case MsgPackTypeId.MpArray16:
                case MsgPackTypeId.MpArray32: item = new MpArray(settings); break;

                //case MsgPackTypeId.MpMap4:
                case MsgPackTypeId.MpMap16:
                case MsgPackTypeId.MpMap32: item = new MpMap(settings); break;

                case MsgPackTypeId.MpFExt1:
                case MsgPackTypeId.MpFExt2:
                case MsgPackTypeId.MpFExt4:
                case MsgPackTypeId.MpFExt8:
                case MsgPackTypeId.MpFExt16:
                case MsgPackTypeId.MpExt8:
                case MsgPackTypeId.MpExt16:
                case MsgPackTypeId.MpExt32: item = new MpExt(settings); break;

                case MsgPackTypeId.NeverUsed:
                {
                    long pos = stream.Position - 1;
                    if (settings.ContinueProcessingOnBreakingError)
                    {
                        FindNextValidTypeId(stream);
                    }
                    return(new MpError(settings, pos, MsgPackTypeId.NeverUsed, "The specification specifically states that the value 0xC1 should never be used.")
                        {
                            storedLength = (stream.Position - pos)
                        });
                }
                }

                if (ReferenceEquals(item, null))
                {
                    if (((byte)type & 0xE0) == 0xE0 || (((byte)type & 0x80) == 0))
                    {
                        item = new MpInt(settings);
                    }
                    else if (((byte)type & 0xA0) == 0xA0)
                    {
                        item = new MpString(settings);
                    }
                    else if (((byte)type & 0x90) == 0x90)
                    {
                        item = new MpArray(settings);
                    }
                    else if (((byte)type & 0x80) == 0x80)
                    {
                        item = new MpMap(settings);
                    }
                }

                if (!ReferenceEquals(item, null))
                {
                    item.storedOffset = stream.Position - 1;
                    item._settings    = settings; // maybe redundent, but want to be sure
                    MsgPackItem ret = item.Read(type, stream);
                    item.storedLength = stream.Position - item.storedOffset;
                    if (!ReferenceEquals(item, ret))
                    {
                        ret.storedLength = item.storedLength;
                    }
                    return(ret);
                }
                else
                {
                    long pos = stream.Position - 1;
                    if (settings.ContinueProcessingOnBreakingError)
                    {
                        FindNextValidTypeId(stream);
                    }
                    return(new MpError(settings, pos, type, "The type identifier with value 0x", BitConverter.ToString(new byte[] { (byte)type }),
                                       " is either new or invalid. It is not (yet) implemented in this version of LsMsgPack.")
                    {
                        storedLength = (stream.Position - pos)
                    });
                }
            }catch (Exception ex) {
                long pos = stream.Position - 1;
                if (settings.ContinueProcessingOnBreakingError)
                {
                    FindNextValidTypeId(stream);
                }
                return(new MpError(settings, new MsgPackException("Error while reading data.", ex, stream.Position, (MsgPackTypeId)typeByte))
                {
                    storedOffset = pos,
                    storedLength = (stream.Position - pos),
                    PartialItem = item
                });
            }
        }
예제 #26
0
 public MsgPackItem(MsgPackSettings settings)
 {
     _settings    = settings;
     _isBestGuess = _settings.FileContainsErrors;
 }
예제 #27
0
        public static MsgPackItem Pack(object value, MsgPackSettings settings)
        {
            if (ReferenceEquals(value, null))
            {
                return(new MpNull(settings));
            }
            if (value is bool)
            {
                return new MpBool(settings)
                       {
                           Value = value
                       }
            }
            ;
            if (value is sbyte ||
                value is short ||
                value is int ||
                value is long ||
                value is byte ||
                value is ushort ||
                value is uint ||
                value is ulong)
            {
                return new MpInt(settings)
                       {
                           Value = value
                       }
            }
            ;
            if (value is float ||
                value is double)
            {
                return new MpFloat(settings)
                       {
                           Value = value
                       }
            }
            ;
            if (value is string)
            {
                return new MpString(settings)
                       {
                           Value = value
                       }
            }
            ;
            if (value is byte[])
            {
                return new MpBin(settings)
                       {
                           Value = value
                       }
            }
            ;
            if (value is object[])
            {
                return new MpArray(settings)
                       {
                           Value = value
                       }
            }
            ;

            Type valuesType = value.GetType();

            if (valuesType.IsEnum)
            {
                return(new MpInt(settings).SetEnumVal(value));
            }
            if (IsSubclassOfArrayOfRawGeneric(typeof(KeyValuePair <,>), valuesType))
            {
                return new MpMap(settings)
                       {
                           Value = value
                       }
            }
            ;
            if (IsSubclassOfRawGeneric(typeof(Dictionary <,>), valuesType))
            {
                return new MpMap(settings)
                       {
                           Value = value
                       }
            }
            ;
            if (valuesType.IsArray)
            {
                return new MpArray(settings)
                       {
                           Value = ((IEnumerable)value).Cast <Object>().ToArray()
                       }
            }
            ;
            if (typeof(IEnumerable).IsAssignableFrom(valuesType))
            {
                return new MpArray(settings)
                       {
                           Value = ((IEnumerable)value).Cast <Object>().ToArray()
                       }
            }
            ;

            // Extension types will come in like this most of the time:
            MsgPackItem val = value as MsgPackItem;

            if (!ReferenceEquals(val, null))
            {
                val._settings = settings;

                return(val);
            }

            return(MsgPackSerializer.SerializeObject(value, settings));
        }
예제 #28
0
 public MsgPackVarLen(MsgPackSettings settings) : base(settings)
 {
 }
예제 #29
0
 public MpBool(MsgPackSettings settings) : base(settings)
 {
 }
예제 #30
0
 public MpInt(MsgPackSettings settings) : base(settings)
 {
 }