コード例 #1
0
        internal StreamDecoder(int streamBufferSize, Action <MessageHeader> controlMsgHandler, Action <MessageHeader, SecsMessage> dataMsgHandler)
        {
            _buffer            = new byte[streamBufferSize];
            _BufferOffset      = 0;
            _decodeIndex       = 0;
            _dataMsgHandler    = dataMsgHandler;
            _controlMsgHandler = controlMsgHandler;

            _decoders = new Decoder[] {
                // 0: get total message length 4 bytes
                (ref int length, out int need) =>
                {
                    if (!CheckAvailable(ref length, 4, out need))
                    {
                        return(0);
                    }

                    Array.Reverse(_buffer, _decodeIndex, 4);
                    _messageDataLength = BitConverter.ToUInt32(_buffer, _decodeIndex);
                    Trace.WriteLine($"Get Message Length: {_messageDataLength}");
                    _decodeIndex += 4;
                    length       -= 4;
                    return(1);
                },
                // 1: get message header 10 bytes
                (ref int length, out int need) =>
                {
                    if (!CheckAvailable(ref length, 10, out need))
                    {
                        return(1);
                    }

                    _msgHeader          = new MessageHeader(_buffer, _decodeIndex);
                    _decodeIndex       += 10;
                    _messageDataLength -= 10;
                    length             -= 10;
                    if (_messageDataLength == 0)
                    {
                        if (_msgHeader.MessageType == MessageType.DataMessage)
                        {
                            _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty));
                        }
                        else
                        {
                            _controlMsgHandler(_msgHeader);
                        }
                        return(0);
                    }

                    if (length >= _messageDataLength)
                    {
                        Trace.WriteLine("Get Complete Data Message with total data");
                        _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, _buffer, ref _decodeIndex));
                        length            -= (int)_messageDataLength;
                        _messageDataLength = 0;
                        return(0);    //completeWith message received
                    }
                    return(2);
                },
                // 2: get _format + lengthBits(2bit) 1 byte
                (ref int length, out int need) =>
                {
                    if (!CheckAvailable(ref length, 1, out need))
                    {
                        return(2);
                    }

                    _format     = (SecsFormat)(_buffer[_decodeIndex] & 0xFC);
                    _lengthBits = (byte)(_buffer[_decodeIndex] & 3);
                    _decodeIndex++;
                    _messageDataLength--;
                    length--;
                    return(3);
                },
                // 3: get _itemLength _lengthBits bytes, at most 3 byte
                (ref int length, out int need) =>
                {
                    if (!CheckAvailable(ref length, _lengthBits, out need))
                    {
                        return(3);
                    }

                    Array.Copy(_buffer, _decodeIndex, _itemLengthBytes, 0, _lengthBits);
                    Array.Reverse(_itemLengthBytes, 0, _lengthBits);

                    _itemLength = BitConverter.ToInt32(_itemLengthBytes, 0);
                    Array.Clear(_itemLengthBytes, 0, 4);
                    Trace.WriteLineIf(_format != SecsFormat.List, $"Get format: {_format}, length: {_itemLength}");

                    _decodeIndex       += _lengthBits;
                    _messageDataLength -= _lengthBits;
                    length             -= _lengthBits;
                    return(4);
                },
                // 4: get item value
                (ref int length, out int need) =>
                {
                    need = 0;
                    Item item;
                    if (_format == SecsFormat.List)
                    {
                        if (_itemLength == 0)
                        {
                            item = Item.L();
                        }
                        else
                        {
                            _stack.Push(new List <Item>(_itemLength));
                            return(2);
                        }
                    }
                    else
                    {
                        if (!CheckAvailable(ref length, _itemLength, out need))
                        {
                            return(4);
                        }

                        item = _itemLength == 0 ? _format.BytesDecode() : _format.BytesDecode(_buffer, ref _decodeIndex, ref _itemLength);
                        Trace.WriteLine($"Complete Item: {_format}");

                        _decodeIndex       += _itemLength;
                        _messageDataLength -= (uint)_itemLength;
                        length             -= _itemLength;
                    }

                    if (_stack.Count == 0)
                    {
                        Trace.WriteLine("Get Complete Data Message by stream decoded");
                        _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty, item));
                        return(0);
                    }

                    var list = _stack.Peek();
                    list.Add(item);
                    while (list.Count == list.Capacity)
                    {
                        item = Item.L(_stack.Pop());
                        Trace.WriteLine($"Complete List: {item.Count}");
                        if (_stack.Count > 0)
                        {
                            list = _stack.Peek();
                            list.Add(item);
                        }
                        else
                        {
                            Trace.WriteLine("Get Complete Data Message by stream decoded");
                            _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty, item));
                            return(0);
                        }
                    }

                    return(2);
                },
            };
        }
コード例 #2
0
ファイル: SecsGem.cs プロジェクト: dzp0839/secs4net1
            internal SecsDecoder(Action <Header> controlMsgHandler, Action <Header, SecsMessage> msgHandler)
            {
                DataMsgHandler    = msgHandler;
                ControlMsgHandler = controlMsgHandler;

                decoders = new Decoder[] {
                    #region decoders[0]: get total message length 4 bytes
                    (byte[] data, int length, ref int index, out int need) =>
                    {
                        if (!CheckAvailable(length, index, 4, out need))
                        {
                            return(0);
                        }

                        Array.Reverse(data, index, 4);
                        _messageLength = BitConverter.ToUInt32(data, index);
                        Trace.WriteLine("Get Message Length =" + _messageLength);
                        index += 4;

                        return(1);
                    },
                    #endregion
                    #region decoders[1]: get message header 10 bytes
                    (byte[] data, int length, ref int index, out int need) =>
                    {
                        if (!CheckAvailable(length, index, 10, out need))
                        {
                            return(1);
                        }

                        _msgHeader = new Header(new byte[10]);
                        Array.Copy(data, index, _msgHeader.Bytes, 0, 10);
                        index          += 10;
                        _messageLength -= 10;
                        if (_messageLength == 0)
                        {
                            if (_msgHeader.MessageType == MessageType.Data_Message)
                            {
                                ProcessMessage(new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty));
                            }
                            else
                            {
                                ControlMsgHandler(_msgHeader);
                                _messageLength = 0;
                            }
                            return(0);
                        }
                        else if (length - index >= _messageLength)
                        {
                            ProcessMessage(new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, data, ref index));
                            return(0); //completeWith message received
                        }
                        return(2);
                    },
                    #endregion
                    #region decoders[2]: get _format + lengthBits(2bit) 1 byte
                    (byte[] data, int length, ref int index, out int need) =>
                    {
                        if (!CheckAvailable(length, index, 1, out need))
                        {
                            return(2);
                        }

                        _format     = (SecsFormat)(data[index] & 0xFC);
                        _lengthBits = (byte)(data[index] & 3);
                        index++;
                        _messageLength--;
                        return(3);
                    },
                    #endregion
                    #region decoders[3]: get _itemLength _lengthBits bytes
                    (byte[] data, int length, ref int index, out int need) =>
                    {
                        if (!CheckAvailable(length, index, _lengthBits, out need))
                        {
                            return(3);
                        }

                        byte[] itemLengthBytes = new byte[4];
                        Array.Copy(data, index, itemLengthBytes, 0, _lengthBits);
                        Array.Reverse(itemLengthBytes, 0, _lengthBits);

                        _itemLength = BitConverter.ToInt32(itemLengthBytes, 0);
                        Array.Clear(itemLengthBytes, 0, 4);

                        index          += _lengthBits;
                        _messageLength -= _lengthBits;
                        return(4);
                    },
                    #endregion
                    #region decoders[4]: get item value
                    (byte[] data, int length, ref int index, out int need) =>
                    {
                        need = 0;
                        Item item = null;
                        if (_format == SecsFormat.List)
                        {
                            if (_itemLength == 0)
                            {
                                item = Item.L();
                            }
                            else
                            {
                                _stack.Push(new List <Item>(_itemLength));
                                return(2);
                            }
                        }
                        else
                        {
                            if (!CheckAvailable(length, index, _itemLength, out need))
                            {
                                return(4);
                            }

                            item            = _itemLength == 0 ? _format.BytesDecode() : _format.BytesDecode(data, index, _itemLength);
                            index          += _itemLength;
                            _messageLength -= (uint)_itemLength;
                        }

                        if (_stack.Count > 0)
                        {
                            var list = _stack.Peek();
                            list.Add(item);
                            while (list.Count == list.Capacity)
                            {
                                item = Item.L(_stack.Pop());
                                if (_stack.Count > 0)
                                {
                                    list = _stack.Peek();
                                    list.Add(item);
                                }
                                else
                                {
                                    ProcessMessage(new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty, item));
                                    return(0);
                                }
                            }
                        }
                        return(2);
                    },
                    #endregion
                };
            }