bool ReadByte_Length(byte b)
        {
            if (_bytesExpected == 0)
            {
                if ((b & 0x80) != 0)
                {
                    _bytesExpected = (b & 0x7F) + 1;
                }
                else
                {
                    _bytesExpected = 1;
                }

                if (_bytesExpected > 5)
                {
                    ThrowError(104, "Number of length octets out of bounds");
                }
            }

            _bytesRead++;

            if (_bytesRead == _bytesExpected)
            {
                var input = new BerMemoryInput(_buffer);

                if (Type == 0)
                {
                    OuterLength = BerEncoding.DecodeLength(input);

                    if (OuterLength == 0)
                    {
                        ThrowError(102, "Zero outer length encountered");
                    }

                    ResetState(DecodeState.Tag);
                }
                else
                {
                    Length = BerEncoding.DecodeLength(input);
                    var isEofOK = Length == 0;

                    if (IsContainer)
                    {
                        ResetState(DecodeState.Tag);

                        OnNewContainer();
                        PushContainer();

                        DisposeCurrentTlv();
                        return(isEofOK);
                    }

                    if (Length == 0)
                    {
                        OnValueReady();
                    }
                    else
                    {
                        ResetState(DecodeState.Value);
                        _buffer.Capacity = (int)Length;
                    }

                    return(isEofOK);
                }
            }

            return(false);
        }
        /// <summary>
        /// Read the next TLTLV and publishes information like <see cref="BerLib.BerReaderBase.Tag" />,
        /// <see cref="BerLib.BerReaderBase.Length" />, <see cref="BerLib.BerReaderBase.Type" /> and
        /// <see cref="BerLib.BerReaderBase.IsContainer" />.
        /// Use one of the Get() functions of BerLib.BerReaderBase to retrieve the Value.
        /// </summary>
        /// <returns>True if a valid TLTLV has been read, otherwise false.</returns>
        public bool Read()
        {
            Debug.Assert(_input != null);
            var typeTag = BerTag.Zero;

            DisposeCurrentTlv();

            if (_parentReader != null && // non top-level read?
                this.Eof)
            {
                HandleEof();
                return(false);
            }

            Tag = BerEncoding.DecodeTag(this);

            if (Tag.IsZero)
            {
                // terminator of indefinite length field: 4 zeros (outer length AND inner length must be indefinite
                if (ReadByte() == 0 &&
                    ReadByte() == 0 &&
                    ReadByte() == 0)
                {
                    HandleEof();
                    return(false);
                }
                else
                {
                    ThrowError(10, "Invalid zero tag: 0x00");
                }
            }

            OuterLength = BerEncoding.DecodeLength(this);

            if (OuterLength == 0)
            {
                ThrowError(13, "Zero outer length encountered");
            }

            if (Tag.IsContainer &&
                Tag.Class != BerClass.Universal)
            {
                typeTag = BerEncoding.DecodeTag(this);
                Length  = BerEncoding.DecodeLength(this);

                if ((Length == BerDefinitions.IndefiniteLength) != (OuterLength == BerDefinitions.IndefiniteLength))
                {
                    ThrowError(12, "Outer and inner tag must use the same length form");
                }
            }
            else
            {
                ThrowError(14, "Implicit tag or universal outer tag found");
            }

            IsContainer = typeTag.IsContainer;
            Tag         = Tag.ToPrimitive(); // clear container flag
            Type        = typeTag.NumberAsType;

            if (Length == BerDefinitions.IndefiniteLength &&
                IsContainer == false)
            {
                ThrowError(11, "Indefinite length form is only allowed on containers");
            }

            if (IsContainer == false &&
                Length > 0)
            {
                var value = new byte[Length];

                for (int index = 0; index < Length; index++)
                {
                    value[index] = ReadByte();
                }

                Value = value;
            }

            return(true);
        }