bool ReadByte_Tag(byte b)
        {
            if (b == 0 && _bytesRead == 0)
            {
                ResetState(DecodeState.Terminator);
                return(false);
            }

            if (_bytesRead > 12)
            {
                ThrowError(103, "Number of tag octets out of bounds");
            }

            if (_bytesRead == 0 && (b & 0x1F) != 0x1F ||
                _bytesRead > 0 && (b & 0x80) == 0)
            {
                var input = new BerMemoryInput(_buffer);

                if (Tag.IsZero)
                {
                    // no outer tag read yet -> read outer tag
                    var tag = BerEncoding.DecodeTag(input);

                    if (tag.Class == BerClass.Universal)
                    {
                        ThrowError(107, "Universal outer tag encountered");
                    }

                    if (tag.IsContainer == false)
                    {
                        ThrowError(108, "Primitive outer tag encountered");
                    }

                    Tag = tag.ToPrimitive(); // clear container flag
                }
                else
                {
                    // outer tag already read -> read inner tag (type tag)
                    var typeTag = BerEncoding.DecodeTag(input);
                    var type    = typeTag.NumberAsType;

                    if (BerType.IsApplicationDefined(type) == false)
                    {
                        if (typeTag.Class != BerClass.Universal)
                        {
                            ThrowError(110, "Non-universal inner tag encountered");
                        }

                        if (type == 0 || type >= BerType.LastUniversal)
                        {
                            ThrowError(109, "Invalid BER type encountered");
                        }
                    }

                    IsContainer = typeTag.IsContainer;
                    Type        = type;
                }

                ResetState(DecodeState.Length);
                return(false);
            }

            _bytesRead++;
            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);
        }