Exemplo n.º 1
0
            private bool ParseItemSequenceTag(IByteSource source)
            {
                if (this.parseStage == ParseStage.Tag)
                {
                    source.Mark();

                    if (!source.Require(8))
                    {
                        this.result = DicomReaderResult.Suspended;
                        return(false);
                    }

                    var group   = source.GetUInt16();
                    var element = source.GetUInt16();

                    this._tag = new DicomTag(@group, element);

                    if (this._tag != DicomTag.Item && this._tag != DicomTag.SequenceDelimitationItem)
                    {
                        // assume invalid sequence
                        source.Rewind();
                        if (!this._implicit)
                        {
                            source.PopMilestone();
                        }
                        this.observer.OnEndSequence();
                        if (this.badPrivateSequence)
                        {
                            this.isExplicitVR       = !this.isExplicitVR;
                            this.badPrivateSequence = false;
                        }
                        return(false);
                    }

                    this.length = source.GetUInt32();

                    if (this._tag == DicomTag.SequenceDelimitationItem)
                    {
                        // #64, in case explicit length has been specified despite occurrence of Sequence Delimitation Item
                        if (source.HasReachedMilestone() && source.MilestonesCount > this.sequenceDepth)
                        {
                            this.ResetState();
                            return(true);
                        }

                        // end of sequence
                        this.observer.OnEndSequence();
                        if (this.badPrivateSequence)
                        {
                            this.isExplicitVR       = !this.isExplicitVR;
                            this.badPrivateSequence = false;
                        }
                        this.ResetState();
                        return(false);
                    }

                    this.parseStage = ParseStage.Value;
                }
                return(true);
            }
Exemplo n.º 2
0
 private void ResetState()
 {
     this.parseStage = ParseStage.Tag;
     this._tag       = null;
     this._entry     = null;
     this._vr        = null;
     this.length     = 0;
 }
Exemplo n.º 3
0
 private void ResetState()
 {
     _parseStage = ParseStage.Tag;
     _tag        = null;
     _entry      = null;
     _vr         = null;
     _length     = 0;
 }
Exemplo n.º 4
0
            private bool ParseTag(IByteSource source)
            {
                if (_parseStage == ParseStage.Tag)
                {
                    source.Mark();

                    if (!source.Require(4))
                    {
                        _result = DicomReaderResult.Suspended;
                        return(false);
                    }

                    var group   = source.GetUInt16();
                    var element = source.GetUInt16();
                    DicomPrivateCreator creator = null;

                    // according to
                    // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.8.html
                    // The requirements of this section do not allow any use of elements in the ranges
                    // (gggg,0001-000F) and (gggg,0100-0FFF) where gggg is odd.
                    // So element at [0x0100-0x0FFF] should not has a creator
                    if (@group.IsOdd() && element >= 0x1000)
                    {
                        var card = (uint)(@group << 16) + (uint)(element >> 8);
                        lock (_locker)
                        {
                            if (_private.TryGetValue(card, out string pvt))
                            {
                                creator = _dictionary.GetPrivateCreator(pvt);
                            }
                        }
                    }

                    _tag   = new DicomTag(@group, element, creator);
                    _entry = _dictionary[_tag];

                    if (!_tag.IsPrivate && _entry != null && _entry.MaskTag == null)
                    {
                        _tag = _entry.Tag; // Use dictionary tag
                    }

                    if (_stop != null &&
                        _stop(new ParseState {
                        Tag = _tag, SequenceDepth = _sequenceDepth
                    }))
                    {
                        _result = DicomReaderResult.Stopped;
                        return(false);
                    }

                    _parseStage = ParseStage.VR;
                }
                return(true);
            }
Exemplo n.º 5
0
            private bool ParseTag(IByteSource source)
            {
                if (this.parseStage == ParseStage.Tag)
                {
                    source.Mark();

                    if (!source.Require(4))
                    {
                        this.result = DicomReaderResult.Suspended;
                        return(false);
                    }

                    var group   = source.GetUInt16();
                    var element = source.GetUInt16();
                    DicomPrivateCreator creator = null;

                    if (@group.IsOdd() && element > 0x00ff)
                    {
                        var card = (uint)(@group << 16) + (uint)(element >> 8);
                        lock (this.locker)
                        {
                            string pvt;
                            if (this._private.TryGetValue(card, out pvt))
                            {
                                creator = this.dictionary.GetPrivateCreator(pvt);
                            }
                        }
                    }

                    this._tag   = new DicomTag(@group, element, creator);
                    this._entry = this.dictionary[this._tag];

                    if (!this._tag.IsPrivate && this._entry != null && this._entry.MaskTag == null)
                    {
                        this._tag = this._entry.Tag; // Use dictionary tag
                    }

                    if (this.stop != null &&
                        this.stop(new ParseState {
                        Tag = this._tag, SequenceDepth = this.sequenceDepth
                    }))
                    {
                        this.result = DicomReaderResult.Stopped;
                        return(false);
                    }

                    this.parseStage = ParseStage.VR;
                }
                return(true);
            }
Exemplo n.º 6
0
            private bool ParseFragmentSequenceValue(IByteSource source)
            {
                if (_parseStage == ParseStage.Value)
                {
                    if (!source.Require(_length))
                    {
                        _result = DicomReaderResult.Suspended;
                        return(false);
                    }

                    var buffer = source.GetBuffer(_length);
                    buffer = EndianByteBuffer.Create(buffer, source.Endian, _fragmentItem == 1 ? 4 : _vr.UnitSize);
                    _observer.OnFragmentSequenceItem(source, buffer);

                    _parseStage = ParseStage.Tag;
                }
                return(true);
            }
Exemplo n.º 7
0
            private async Task <bool> ParseFragmentSequenceValueAsync(IByteSource source)
            {
                if (this.parseStage == ParseStage.Value)
                {
                    if (!source.Require(this.length))
                    {
                        this.result = DicomReaderResult.Suspended;
                        return(false);
                    }

                    var buffer = await source.GetBufferAsync(this.length).ConfigureAwait(false);

                    buffer = EndianByteBuffer.Create(buffer, source.Endian, this.fragmentItem == 1 ? 4 : this._vr.UnitSize);
                    this.observer.OnFragmentSequenceItem(source, buffer);

                    this.parseStage = ParseStage.Tag;
                }
                return(true);
            }
Exemplo n.º 8
0
            private bool ParseFragmentSequenceTag(IByteSource source)
            {
                if (_parseStage == ParseStage.Tag)
                {
                    source.Mark();

                    if (!source.Require(8))
                    {
                        _result = DicomReaderResult.Suspended;
                        return(false);
                    }

                    var group   = source.GetUInt16();
                    var element = source.GetUInt16();

                    var tag = new DicomTag(@group, element);

                    if (tag != DicomTag.Item && tag != DicomTag.SequenceDelimitationItem)
                    {
                        throw new DicomReaderException($"Unexpected tag in DICOM fragment sequence: {tag}");
                    }

                    _length = source.GetUInt32();

                    if (tag == DicomTag.SequenceDelimitationItem)
                    {
                        // end of fragment
                        _observer.OnEndFragmentSequence();
                        _fragmentItem = 0;
                        ResetState();
                        return(false);
                    }

                    _fragmentItem++;
                    _parseStage = ParseStage.Value;
                }
                return(true);
            }
Exemplo n.º 9
0
            private bool ParseTag(IByteSource source)
            {
                if (this.parseStage == ParseStage.Tag)
                {
                    source.Mark();

                    if (!source.Require(4))
                    {
                        this.result = DicomReaderResult.Suspended;
                        return false;
                    }

                    var group = source.GetUInt16();
                    var element = source.GetUInt16();
                    DicomPrivateCreator creator = null;

                    if (@group.IsOdd() && element > 0x00ff)
                    {
                        var card = (uint)(@group << 16) + (uint)(element >> 8);
                        lock (this.locker)
                        {
                            string pvt;
                            if (this._private.TryGetValue(card, out pvt))
                            {
                                creator = this.dictionary.GetPrivateCreator(pvt);
                            }
                        }
                    }

                    this._tag = new DicomTag(@group, element, creator);
                    this._entry = this.dictionary[this._tag];

                    if (!this._tag.IsPrivate && this._entry != null && this._entry.MaskTag == null)
                    {
                        this._tag = this._entry.Tag; // Use dictionary tag
                    }

                    if (this.stop != null
                        && this.stop(new ParseState { Tag = this._tag, SequenceDepth = this.sequenceDepth }))
                    {
                        this.result = DicomReaderResult.Stopped;
                        return false;
                    }

                    this.parseStage = ParseStage.VR;
                }
                return true;
            }
Exemplo n.º 10
0
 private void ResetState()
 {
     this.parseStage = ParseStage.Tag;
     this._tag = null;
     this._entry = null;
     this._vr = null;
     this.length = 0;
 }
Exemplo n.º 11
0
            private async Task<bool> ParseFragmentSequenceValueAsync(IByteSource source)
            {
                if (this.parseStage == ParseStage.Value)
                {
                    if (!source.Require(this.length))
                    {
                        this.result = DicomReaderResult.Suspended;
                        return false;
                    }

                    var buffer = await source.GetBufferAsync(this.length).ConfigureAwait(false);
                    buffer = EndianByteBuffer.Create(buffer, source.Endian, this.fragmentItem == 1 ? 4 : this._vr.UnitSize);
                    this.observer.OnFragmentSequenceItem(source, buffer);

                    this.parseStage = ParseStage.Tag;
                }
                return true;
            }
Exemplo n.º 12
0
            private bool ParseFragmentSequenceTag(IByteSource source)
            {
                if (this.parseStage == ParseStage.Tag)
                {
                    source.Mark();

                    if (!source.Require(8))
                    {
                        this.result = DicomReaderResult.Suspended;
                        return false;
                    }

                    var group = source.GetUInt16();
                    var element = source.GetUInt16();

                    DicomTag tag = new DicomTag(@group, element);

                    if (tag != DicomTag.Item && tag != DicomTag.SequenceDelimitationItem)
                    {
                        throw new DicomReaderException("Unexpected tag in DICOM fragment sequence: {0}", tag);
                    }

                    this.length = source.GetUInt32();

                    if (tag == DicomTag.SequenceDelimitationItem)
                    {
                        // end of fragment
                        this.observer.OnEndFragmentSequence();
                        this.fragmentItem = 0;
                        this.ResetState();
                        return false;
                    }

                    this.fragmentItem++;
                    this.parseStage = ParseStage.Value;
                }
                return true;
            }
Exemplo n.º 13
0
            private bool ParseItemSequenceTag(IByteSource source)
            {
                if (this.parseStage == ParseStage.Tag)
                {
                    source.Mark();

                    if (!source.Require(8))
                    {
                        this.result = DicomReaderResult.Suspended;
                        return false;
                    }

                    var group = source.GetUInt16();
                    var element = source.GetUInt16();

                    this._tag = new DicomTag(@group, element);

                    if (this._tag != DicomTag.Item && this._tag != DicomTag.SequenceDelimitationItem)
                    {
                        // assume invalid sequence
                        source.Rewind();
                        if (!this._implicit)
                        {
                            source.PopMilestone();
                        }
                        this.observer.OnEndSequence();
                        if (this.badPrivateSequence)
                        {
                            this.isExplicitVR = !this.isExplicitVR;
                            this.badPrivateSequence = false;
                        }
                        return false;
                    }

                    this.length = source.GetUInt32();

                    if (this._tag == DicomTag.SequenceDelimitationItem)
                    {
                        // #64, in case explicit length has been specified despite occurrence of Sequence Delimitation Item
                        if (source.HasReachedMilestone() && source.MilestonesCount > this.sequenceDepth)
                        {
                            this.ResetState();
                            return true;
                        }

                        // end of sequence
                        this.observer.OnEndSequence();
                        if (this.badPrivateSequence)
                        {
                            this.isExplicitVR = !this.isExplicitVR;
                            this.badPrivateSequence = false;
                        }
                        this.ResetState();
                        return false;
                    }

                    this.parseStage = ParseStage.Value;
                }
                return true;
            }
Exemplo n.º 14
0
Arquivo: Parser.cs Projeto: shz/pointy
 void EmitParseError(Error error, string extra = null)
 {
     var e = OnParseError;
     if (e != null) e(error, extra);
     Stage = ParseStage.Error;
 }
Exemplo n.º 15
0
            private async Task <bool> ParseValueAsync(IByteSource source)
            {
                if (_parseStage == ParseStage.Value)
                {
                    // check dictionary for VR after reading length to handle 16-bit lengths
                    // check before reading value to handle SQ elements
                    var parsedVR = _vr;

                    // check dictionary for VR after reading length to handle 16-bit lengths
                    // check before reading value to handle SQ elements
                    if (_vr == DicomVR.Implicit || (_vr == DicomVR.UN && _isExplicitVR))
                    {
                        var entry = _dictionary[_tag];
                        if (entry != null)
                        {
                            _vr = entry.ValueRepresentations.FirstOrDefault();
                        }

                        if (_vr == null)
                        {
                            _vr = DicomVR.UN;
                        }
                    }

                    if (_tag == DicomTag.ItemDelimitationItem || _tag == DicomTag.SequenceDelimitationItem)
                    {
                        // end of sequence item
                        return(false);
                    }

                    while (_vr == DicomVR.SQ && _tag.IsPrivate && _length > 0)
                    {
                        if (!IsPrivateSequence(source))
                        {
                            _vr = DicomVR.UN;
                            break;
                        }

                        if (IsPrivateSequenceBad(source, _length, _isExplicitVR))
                        {
                            _badPrivateSequence = true;
                            // store the depth of the bad sequence, we only want to switch back once we've processed
                            // the entire sequence, regardless of any sub-sequences.
                            _badPrivateSequenceDepth = _sequenceDepth;
                            _isExplicitVR            = !_isExplicitVR;
                        }
                        break;
                    }

                    var curIndex = source.Position;
                    // Fix to handle sequence items not associated with any sequence (#364)
                    if (_tag.Equals(DicomTag.Item))
                    {
                        source.Rewind();
                        _vr = DicomVR.SQ;
                    }

                    if (_vr == DicomVR.SQ)
                    {
                        // start of sequence
                        _observer.OnBeginSequence(source, _tag, _length);
                        _parseStage = ParseStage.Tag;
                        if (_length == 0)
                        {
                            _implicit = false;
                            source.PushMilestone((uint)(source.Position - curIndex));
                        }
                        else if (_length != _undefinedLength)
                        {
                            _implicit = false;
                            source.PushMilestone(_length);
                        }
                        else
                        {
                            _implicit = true;
                        }
                        var last = source.Position;

                        // Conformance with CP-246 (#177)
                        var needtoChangeEndian = false;
                        if (parsedVR == DicomVR.UN && !_tag.IsPrivate)
                        {
                            _implicit          = true;
                            needtoChangeEndian = source.Endian == Endian.Big;
                        }
                        if (needtoChangeEndian)
                        {
                            source.Endian = Endian.Little;
                        }

                        await ParseItemSequenceAsync(source).ConfigureAwait(false);

                        if (needtoChangeEndian)
                        {
                            source.Endian = Endian.Big;
                        }

                        // Aeric Sylvan - https://github.com/rcd/fo-dicom/issues/62#issuecomment-46248073
                        // Fix reading of SQ with parsed VR of UN
                        if (source.Position > last || _length == 0)
                        {
                            return(true);
                        }

                        _parseStage = ParseStage.Value;
                        _vr         = parsedVR;
                    }

                    if (_length == _undefinedLength)
                    {
                        _observer.OnBeginFragmentSequence(source, _tag, _vr);
                        _parseStage = ParseStage.Tag;
                        await ParseFragmentSequenceAsync(source).ConfigureAwait(false);

                        return(true);
                    }

                    if (!source.Require(_length))
                    {
                        _result = DicomReaderResult.Suspended;
                        return(false);
                    }

                    var buffer = await source.GetBufferAsync(_length).ConfigureAwait(false);

                    if (!_vr.IsString)
                    {
                        buffer = EndianByteBuffer.Create(buffer, source.Endian, _vr.UnitSize);
                    }
                    _observer.OnElement(source, _tag, _vr, buffer);

                    // parse private creator value and add to lookup table
                    // according to
                    // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.8.html
                    // Private Creator Data Elements numbered (gggg,0010-00FF) (gggg is odd)
                    // The VR of the private identification code shall be LO (Long String) and the VM shall be equal to 1.
                    if (_tag.IsPrivate && _tag.Element >= 0x0010 && _tag.Element <= 0x00ff)
                    {
                        var creator =
                            DicomEncoding.Default.GetString(buffer.Data, 0, buffer.Data.Length)
                            .TrimEnd((char)DicomVR.LO.PaddingValue);
                        var card = (uint)(_tag.Group << 16) + _tag.Element;

                        lock (_locker)
                        {
                            _private[card] = creator;
                        }
                    }

                    ResetState();
                }
                return(true);
            }
Exemplo n.º 16
0
            private bool ParseVR(IByteSource source)
            {
                while (_parseStage == ParseStage.VR)
                {
                    if (_tag == DicomTag.Item || _tag == DicomTag.ItemDelimitationItem ||
                        _tag == DicomTag.SequenceDelimitationItem)
                    {
                        _vr         = DicomVR.NONE;
                        _parseStage = ParseStage.Length;
                        break;
                    }

                    if (_isExplicitVR || _badPrivateSequence)
                    {
                        if (!source.Require(2))
                        {
                            _result = DicomReaderResult.Suspended;
                            return(false);
                        }

                        source.Mark();
                        var bytes = source.GetBytes(2);
                        var vr    = Encoding.UTF8.GetString(bytes, 0, bytes.Length);

                        if (string.IsNullOrEmpty(vr.Trim()))
                        {
                            if (_entry != null)
                            {
                                _vr = _entry.ValueRepresentations.FirstOrDefault();
                            }
                        }
                        else if (!DicomVR.TryParse(vr, out _vr))
                        {
                            // unable to parse VR; rewind VR bytes for continued attempt to interpret the data.
                            _vr = DicomVR.Implicit;
                            source.Rewind();
                        }
                    }
                    else
                    {
                        if (_entry != null)
                        {
                            if (_entry == DicomDictionary.UnknownTag)
                            {
                                _vr = DicomVR.UN;
                            }
                            else if (_entry.ValueRepresentations.Contains(DicomVR.OB) &&
                                     _entry.ValueRepresentations.Contains(DicomVR.OW))
                            {
                                _vr = DicomVR.OW; // ???
                            }
                            else
                            {
                                _vr = _entry.ValueRepresentations.FirstOrDefault();
                            }
                        }
                    }

                    if (_vr == null)
                    {
                        _vr = DicomVR.UN;
                    }

                    _parseStage = ParseStage.Length;

                    if (_vr == DicomVR.UN)
                    {
                        if (_tag.Element == 0x0000)
                        {
                            // Group Length to UL
                            // change 20161216: if changing from UN to UL then ParseLength causes a error, since length in UL is 2 bytes while length in UN is 6 bytes.
                            // so the source hat UN and coded the length in 6 bytes. if here the VR was changed to UL then ParseLength would only read 2 bytes and the parser is then wrong.
                            // but no worry: in ParseValue in the first lines there is a lookup in the Dictionary of DicomTags and there the VR is changed to UL so that the value is finally interpreted correctly as UL.
                            // _vr = DicomVR.UL;
                            break;
                        }
                        if (_isExplicitVR)
                        {
                            break;
                        }
                    }

                    if (_tag.IsPrivate)
                    {
                        // according to
                        // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.8.html
                        // Private Creator Data Elements numbered (gggg,0010-00FF) (gggg is odd)
                        // The VR of the private identification code shall be LO (Long String) and the VM shall be equal to 1.
                        if (_tag.Element >= 0x0010 && _tag.Element <= 0x00ff && _vr == DicomVR.UN)
                        {
                            _vr = DicomVR.LO; // force private creator to LO
                        }
                    }
                }
                return(true);
            }
Exemplo n.º 17
0
            private bool ParseVR(IByteSource source)
            {
                while (this.parseStage == ParseStage.VR)
                {
                    if (this._tag == DicomTag.Item || this._tag == DicomTag.ItemDelimitationItem ||
                        this._tag == DicomTag.SequenceDelimitationItem)
                    {
                        this._vr        = DicomVR.NONE;
                        this.parseStage = ParseStage.Length;
                        break;
                    }

                    if (this.isExplicitVR || this.badPrivateSequence)
                    {
                        if (!source.Require(2))
                        {
                            this.result = DicomReaderResult.Suspended;
                            return(false);
                        }

                        source.Mark();
                        var bytes = source.GetBytes(2);
                        var vr    = Encoding.UTF8.GetString(bytes, 0, bytes.Length);

                        if (string.IsNullOrEmpty(vr.Trim()))
                        {
                            if (this._entry != null)
                            {
                                this._vr = this._entry.ValueRepresentations.FirstOrDefault();
                            }
                        }
                        else if (!DicomVR.TryParse(vr, out this._vr))
                        {
                            // unable to parse VR; rewind VR bytes for continued attempt to interpret the data.
                            this._vr = DicomVR.Implicit;
                            source.Rewind();
                        }
                    }
                    else
                    {
                        if (this._entry != null)
                        {
                            if (this._entry == DicomDictionary.UnknownTag)
                            {
                                this._vr = DicomVR.UN;
                            }
                            else if (this._entry.ValueRepresentations.Contains(DicomVR.OB) &&
                                     this._entry.ValueRepresentations.Contains(DicomVR.OW))
                            {
                                this._vr = DicomVR.OW; // ???
                            }
                            else
                            {
                                this._vr = this._entry.ValueRepresentations.FirstOrDefault();
                            }
                        }
                    }

                    if (this._vr == null)
                    {
                        this._vr = DicomVR.UN;
                    }

                    this.parseStage = ParseStage.Length;

                    if (this._vr == DicomVR.UN)
                    {
                        if (this._tag.Element == 0x0000)
                        {
                            // Group Length to UL
                            // change 20161216: if changing from UN to UL then ParseLength causes a error, since length in UL is 2 bytes while length in UN is 6 bytes.
                            // so the source hat UN and coded the length in 6 bytes. if here the VR was changed to UL then ParseLength would only read 2 bytes and the parser is then wrong.
                            // but no worry: in ParseValue in the first lines there is a lookup in the Dictionary of DicomTags and there the VR is changed to UL so that the value is finally interpreted correctly as UL.
                            // this._vr = DicomVR.UL;
                            break;
                        }
                        if (this.isExplicitVR)
                        {
                            break;
                        }
                    }

                    if (this._tag.IsPrivate)
                    {
                        if (this._tag.Element != 0x0000 && this._tag.Element <= 0x00ff && this._vr == DicomVR.UN)
                        {
                            this._vr = DicomVR.LO; // force private creator to LO
                        }
                    }
                }
                return(true);
            }
Exemplo n.º 18
0
        private void Parse()
        {
            MyEvent = null;
            ParseStage    stage           = ParseStage.Object;
            StringBuilder ObjectBuilder   = new StringBuilder();
            StringBuilder FunctionBuilder = new StringBuilder();

            StringBuilder[] ArgBuilder = new StringBuilder[16];
            int             ArgCount   = 0;

            for (int i = 0; i < Value.Count(); i++)
            {
                switch (Value[i])
                {
                case '.':
                    stage = ParseStage.Function;
                    break;

                case '(':
                    stage = ParseStage.Arguments;
                    break;

                case ',':
                    if (stage == ParseStage.Arguments)
                    {
                        ArgCount++;
                    }
                    break;

                case ')':
                    if (ArgBuilder[ArgCount] != null)
                    {
                        ArgCount++;
                    }
                    string[] args = new string[ArgCount];

                    for (int a = 0; a < ArgCount; a++)
                    {
                        if (ArgBuilder[a] != null)
                        {
                            args[a]       = ArgBuilder[a].ToString().ToLower();
                            ArgBuilder[a] = new StringBuilder();
                        }
                    }

                    ArgCount = 0;

                    EventCall e = new EventCall();

                    e.args = args;

                    string ObjectString = ObjectBuilder.ToString();
                    if (!ObjectString.Equals("this"))
                    {
                        e.MyObject = Parent.ParentLevel.FindObject(ObjectString);
                        if (e.MyObject == null)
                        {
                            e.MyObject = Parent.ParentScene;
                        }
                    }
                    else
                    {
                        e.MyObject = Parent;
                    }

                    string FunctionString = FunctionBuilder.ToString().ToLower();
                    foreach (EventType t in EventCall.AllEvents)
                    {
                        if (t.ToString().ToLower().Equals(FunctionString))
                        {
                            e.Function = t;
                            break;
                        }
                    }

                    ObjectBuilder   = new StringBuilder();
                    FunctionBuilder = new StringBuilder();

                    if (MyEvent == null)
                    {
                        MyEvent = e;
                    }
                    else
                    {
                        MyEvent.Add(e);
                    }

                    stage = ParseStage.Object;
                    break;

                default:
                    switch (stage)
                    {
                    case ParseStage.Object:
                        if (Value[i] != ' ')
                        {
                            ObjectBuilder.Append(Value[i]);
                        }
                        break;

                    case ParseStage.Function:
                        if (Value[i] != ' ')
                        {
                            FunctionBuilder.Append(Value[i]);
                        }
                        break;

                    case ParseStage.Arguments:
                        if (ArgBuilder[ArgCount] == null)
                        {
                            ArgBuilder[ArgCount] = new StringBuilder();
                        }
                        ArgBuilder[ArgCount].Append(Value[i]);
                        break;
                    }
                    break;
                }
            }
            NeedsParsing = false;
        }
Exemplo n.º 19
0
            private async Task <bool> ParseValueAsync(IByteSource source)
            {
                if (this.parseStage == ParseStage.Value)
                {
                    // check dictionary for VR after reading length to handle 16-bit lengths
                    // check before reading value to handle SQ elements
                    var parsedVR = this._vr;

                    // check dictionary for VR after reading length to handle 16-bit lengths
                    // check before reading value to handle SQ elements
                    if (this._vr == DicomVR.Implicit || (this._vr == DicomVR.UN && this.isExplicitVR))
                    {
                        var entry = this.dictionary[this._tag];
                        if (entry != null)
                        {
                            this._vr = entry.ValueRepresentations.FirstOrDefault();
                        }

                        if (this._vr == null)
                        {
                            this._vr = DicomVR.UN;
                        }
                    }

                    if (this._tag == DicomTag.ItemDelimitationItem)
                    {
                        // end of sequence item
                        return(false);
                    }

                    while (this._vr == DicomVR.SQ && this._tag.IsPrivate)
                    {
                        if (!IsPrivateSequence(source))
                        {
                            this._vr = DicomVR.UN;
                            break;
                        }

                        if (IsPrivateSequenceBad(source, this.isExplicitVR))
                        {
                            this.badPrivateSequence = true;
                            this.isExplicitVR       = !this.isExplicitVR;
                        }
                        break;
                    }

                    if (this._vr == DicomVR.SQ)
                    {
                        // start of sequence
                        this.observer.OnBeginSequence(source, this._tag, this.length);
                        this.parseStage = ParseStage.Tag;
                        if (this.length != UndefinedLength)
                        {
                            this._implicit = false;
                            source.PushMilestone(this.length);
                        }
                        else
                        {
                            this._implicit = true;
                        }
                        var last = source.Position;

                        // Conformance with CP-246 (#177)
                        var needtoChangeEndian = false;
                        if (parsedVR == DicomVR.UN && !this._tag.IsPrivate)
                        {
                            this._implicit     = true;
                            needtoChangeEndian = source.Endian == Endian.Big;
                        }
                        if (needtoChangeEndian)
                        {
                            source.Endian = Endian.Little;
                        }

                        await this.ParseItemSequenceAsync(source).ConfigureAwait(false);

                        if (needtoChangeEndian)
                        {
                            source.Endian = Endian.Big;
                        }

                        // Aeric Sylvan - https://github.com/rcd/fo-dicom/issues/62#issuecomment-46248073
                        // Fix reading of SQ with parsed VR of UN
                        if (source.Position > last || this.length == 0)
                        {
                            return(true);
                        }

                        this.parseStage = ParseStage.Value;
                        this._vr        = parsedVR;
                    }

                    if (this.length == UndefinedLength)
                    {
                        this.observer.OnBeginFragmentSequence(source, this._tag, this._vr);
                        this.parseStage = ParseStage.Tag;
                        await this.ParseFragmentSequenceAsync(source).ConfigureAwait(false);

                        return(true);
                    }

                    if (!source.Require(this.length))
                    {
                        this.result = DicomReaderResult.Suspended;
                        return(false);
                    }

                    var buffer = await source.GetBufferAsync(this.length).ConfigureAwait(false);

                    if (!this._vr.IsString)
                    {
                        buffer = EndianByteBuffer.Create(buffer, source.Endian, this._vr.UnitSize);
                    }
                    this.observer.OnElement(source, this._tag, this._vr, buffer);

                    // parse private creator value and add to lookup table
                    if (this._tag.IsPrivate && this._tag.Element != 0x0000 && this._tag.Element <= 0x00ff)
                    {
                        var creator =
                            DicomEncoding.Default.GetString(buffer.Data, 0, buffer.Data.Length)
                            .TrimEnd((char)DicomVR.LO.PaddingValue);
                        var card = (uint)(this._tag.Group << 16) + this._tag.Element;

                        lock (this.locker)
                        {
                            this._private[card] = creator;
                        }
                    }

                    this.ResetState();
                }
                return(true);
            }
Exemplo n.º 20
0
            private bool ParseVR(IByteSource source)
            {
                while (this.parseStage == ParseStage.VR)
                {
                    if (this._tag == DicomTag.Item || this._tag == DicomTag.ItemDelimitationItem ||
                        this._tag == DicomTag.SequenceDelimitationItem)
                    {
                        this._vr        = DicomVR.NONE;
                        this.parseStage = ParseStage.Length;
                        break;
                    }

                    if (this.isExplicitVR)
                    {
                        if (!source.Require(2))
                        {
                            this.result = DicomReaderResult.Suspended;
                            return(false);
                        }

                        source.Mark();
                        var bytes = source.GetBytes(2);
                        var vr    = Encoding.UTF8.GetString(bytes, 0, bytes.Length);

                        if (string.IsNullOrWhiteSpace(vr))
                        {
                            if (this._entry != null)
                            {
                                this._vr = this._entry.ValueRepresentations.FirstOrDefault();
                            }
                        }
                        else if (!DicomVR.TryParse(vr, out this._vr))
                        {
                            // unable to parse VR; rewind VR bytes for continued attempt to interpret the data.
                            this._vr = DicomVR.Implicit;
                            source.Rewind();
                        }
                    }
                    else
                    {
                        if (this._entry != null)
                        {
                            if (this._entry == DicomDictionary.UnknownTag)
                            {
                                this._vr = DicomVR.UN;
                            }
                            else if (this._entry.ValueRepresentations.Contains(DicomVR.OB) &&
                                     this._entry.ValueRepresentations.Contains(DicomVR.OW))
                            {
                                this._vr = DicomVR.OW; // ???
                            }
                            else
                            {
                                this._vr = this._entry.ValueRepresentations.FirstOrDefault();
                            }
                        }
                    }

                    if (this._vr == null)
                    {
                        this._vr = DicomVR.UN;
                    }

                    this.parseStage = ParseStage.Length;

                    if (this._vr == DicomVR.UN)
                    {
                        if (this._tag.Element == 0x0000)
                        {
                            // Group Length to UL
                            this._vr = DicomVR.UL;
                            break;
                        }
                        if (this.isExplicitVR)
                        {
                            break;
                        }
                    }

                    if (this._tag.IsPrivate)
                    {
                        if (this._tag.Element != 0x0000 && this._tag.Element <= 0x00ff && this._vr == DicomVR.UN)
                        {
                            this._vr = DicomVR.LO; // force private creator to LO
                        }
                    }
                }
                return(true);
            }
Exemplo n.º 21
0
            private bool ParseVR(IByteSource source)
            {
                while (this.parseStage == ParseStage.VR)
                {
                    if (this._tag == DicomTag.Item || this._tag == DicomTag.ItemDelimitationItem
                        || this._tag == DicomTag.SequenceDelimitationItem)
                    {
                        this._vr = DicomVR.NONE;
                        this.parseStage = ParseStage.Length;
                        break;
                    }

                    if (this.isExplicitVR)
                    {
                        if (!source.Require(2))
                        {
                            this.result = DicomReaderResult.Suspended;
                            return false;
                        }

                        source.Mark();
                        var bytes = source.GetBytes(2);
                        var vr = Encoding.UTF8.GetString(bytes, 0, bytes.Length);

                        if (string.IsNullOrWhiteSpace(vr))
                        {
                            if (this._entry != null)
                            {
                                this._vr = this._entry.ValueRepresentations.FirstOrDefault();
                            }
                        }
                        else if (!DicomVR.TryParse(vr, out this._vr))
                        {
                            // unable to parse VR; rewind VR bytes for continued attempt to interpret the data.
                            this._vr = DicomVR.Implicit;
                            source.Rewind();
                        }
                    }
                    else
                    {
                        if (this._entry != null)
                        {
                            if (this._entry == DicomDictionary.UnknownTag)
                            {
                                this._vr = DicomVR.UN;
                            }
                            else if (this._entry.ValueRepresentations.Contains(DicomVR.OB)
                                     && this._entry.ValueRepresentations.Contains(DicomVR.OW))
                            {
                                this._vr = DicomVR.OW; // ???
                            }
                            else
                            {
                                this._vr = this._entry.ValueRepresentations.FirstOrDefault();
                            }
                        }
                    }

                    if (this._vr == null)
                    {
                        this._vr = DicomVR.UN;
                    }

                    this.parseStage = ParseStage.Length;

                    if (this._vr == DicomVR.UN)
                    {
                        if (this._tag.Element == 0x0000)
                        {
                            // Group Length to UL
                            this._vr = DicomVR.UL;
                            break;
                        }
                        if (this.isExplicitVR)
                        {
                            break;
                        }
                    }

                    if (this._tag.IsPrivate)
                    {
                        if (this._tag.Element != 0x0000 && this._tag.Element <= 0x00ff && this._vr == DicomVR.UN)
                        {
                            this._vr = DicomVR.LO; // force private creator to LO
                        }
                    }
                }
                return true;
            }
Exemplo n.º 22
0
            private bool ParseLength(IByteSource source)
            {
                while (this.parseStage == ParseStage.Length)
                {
                    if (this._tag == DicomTag.Item || this._tag == DicomTag.ItemDelimitationItem
                        || this._tag == DicomTag.SequenceDelimitationItem)
                    {
                        if (!source.Require(4))
                        {
                            this.result = DicomReaderResult.Suspended;
                            return false;
                        }

                        this.length = source.GetUInt32();

                        this.parseStage = ParseStage.Value;
                        break;
                    }

                    if (this.isExplicitVR)
                    {
                        if (this._vr == DicomVR.Implicit)
                        {
                            if (!source.Require(4))
                            {
                                this.result = DicomReaderResult.Suspended;
                                return false;
                            }

                            this.length = source.GetUInt32();

                            // assume that undefined length in implicit VR element is SQ
                            if (this.length == UndefinedLength)
                            {
                                this._vr = DicomVR.SQ;
                            }
                        }
                        else if (this._vr.Is16bitLength)
                        {
                            if (!source.Require(2))
                            {
                                this.result = DicomReaderResult.Suspended;
                                return false;
                            }

                            this.length = source.GetUInt16();
                        }
                        else
                        {
                            if (!source.Require(6))
                            {
                                this.result = DicomReaderResult.Suspended;
                                return false;
                            }

                            source.Skip(2);
                            this.length = source.GetUInt32();

                            // CP-246 (#177) handling
                            // assume that Undefined Length in explicit datasets with VR UN are sequences 
                            // According to CP-246 the sequence shall be handled as ILE, but this will be handled later...
                            // in the current code this needs to be restricted to privates 
                            if (this.length == UndefinedLength && this._vr == DicomVR.UN && this._tag.IsPrivate)
                            {
                                this._vr = DicomVR.SQ;
                            }
                        }
                    }
                    else
                    {
                        if (!source.Require(4))
                        {
                            this.result = DicomReaderResult.Suspended;
                            return false;
                        }

                        this.length = source.GetUInt32();

                        // assume that undefined length in implicit dataset is SQ
                        if (this.length == UndefinedLength && this._vr == DicomVR.UN)
                        {
                            this._vr = DicomVR.SQ;
                        }
                    }

                    this.parseStage = ParseStage.Value;
                }
                return true;
            }
Exemplo n.º 23
0
            private bool ParseLength(IByteSource source)
            {
                while (_parseStage == ParseStage.Length)
                {
                    if (_tag == DicomTag.Item || _tag == DicomTag.ItemDelimitationItem ||
                        _tag == DicomTag.SequenceDelimitationItem)
                    {
                        if (!source.Require(4))
                        {
                            _result = DicomReaderResult.Suspended;
                            return(false);
                        }

                        _length = source.GetUInt32();

                        _parseStage = ParseStage.Value;
                        break;
                    }

                    if (_isExplicitVR || _badPrivateSequence)
                    {
                        if (_vr == DicomVR.Implicit)
                        {
                            if (!source.Require(4))
                            {
                                _result = DicomReaderResult.Suspended;
                                return(false);
                            }

                            _length = source.GetUInt32();

                            // assume that undefined length in implicit VR element is SQ
                            if (_length == _undefinedLength)
                            {
                                _vr = DicomVR.SQ;
                            }
                        }
                        else if (_vr.Is16bitLength)
                        {
                            if (!source.Require(2))
                            {
                                _result = DicomReaderResult.Suspended;
                                return(false);
                            }

                            _length = source.GetUInt16();
                        }
                        else
                        {
                            if (!source.Require(6))
                            {
                                _result = DicomReaderResult.Suspended;
                                return(false);
                            }

                            source.Skip(2);
                            _length = source.GetUInt32();

                            // CP-246 (#177) handling
                            // assume that Undefined Length in explicit datasets with VR UN are sequences
                            // According to CP-246 the sequence shall be handled as ILE, but this will be handled later...
                            // in the current code this needs to be restricted to privates
                            if (_length == _undefinedLength && _vr == DicomVR.UN && _tag.IsPrivate)
                            {
                                _vr = DicomVR.SQ;
                            }
                        }
                    }
                    else
                    {
                        if (!source.Require(4))
                        {
                            _result = DicomReaderResult.Suspended;
                            return(false);
                        }

                        _length = source.GetUInt32();

                        // assume that undefined length in implicit dataset is SQ
                        if (_length == _undefinedLength && _vr == DicomVR.UN)
                        {
                            _vr = DicomVR.SQ;
                        }
                    }

                    _parseStage = ParseStage.Value;
                }
                return(true);
            }
Exemplo n.º 24
0
            private async Task<bool> ParseValueAsync(IByteSource source)
            {
                if (this.parseStage == ParseStage.Value)
                {
                    // check dictionary for VR after reading length to handle 16-bit lengths
                    // check before reading value to handle SQ elements
                    var parsedVR = this._vr;

                    // check dictionary for VR after reading length to handle 16-bit lengths
                    // check before reading value to handle SQ elements
                    if (this._vr == DicomVR.Implicit || (this._vr == DicomVR.UN && this.isExplicitVR))
                    {
                        var entry = this.dictionary[this._tag];
                        if (entry != null)
                        {
                            this._vr = entry.ValueRepresentations.FirstOrDefault();
                        }

                        if (this._vr == null)
                        {
                            this._vr = DicomVR.UN;
                        }
                    }

                    if (this._tag == DicomTag.ItemDelimitationItem)
                    {
                        // end of sequence item
                        return false;
                    }

                    while (this._vr == DicomVR.SQ && this._tag.IsPrivate)
                    {
                        if (!IsPrivateSequence(source))
                        {
                            this._vr = DicomVR.UN;
                            break;
                        }

                        if (IsPrivateSequenceBad(source, this.isExplicitVR))
                        {
                            this.badPrivateSequence = true;
                            this.isExplicitVR = !this.isExplicitVR;
                        }
                        break;
                    }

                    if (this._vr == DicomVR.SQ)
                    {
                        // start of sequence
                        this.observer.OnBeginSequence(source, this._tag, this.length);
                        this.parseStage = ParseStage.Tag;
                        if (this.length != UndefinedLength)
                        {
                            this._implicit = false;
                            source.PushMilestone(this.length);
                        }
                        else
                        {
                            this._implicit = true;
                        }
                        var last = source.Position;

                        // Conformance with CP-246 (#177)
                        var needtoChangeEndian = false;
                        if (parsedVR == DicomVR.UN && !this._tag.IsPrivate)
                        {
                            this._implicit = true;
                            needtoChangeEndian = source.Endian == Endian.Big;
                        }
                        if (needtoChangeEndian)
                        {
                            source.Endian = Endian.Little;
                        }

                        await this.ParseItemSequenceAsync(source).ConfigureAwait(false);

                        if (needtoChangeEndian)
                        {
                            source.Endian = Endian.Big;
                        }

                        // Aeric Sylvan - https://github.com/rcd/fo-dicom/issues/62#issuecomment-46248073
                        // Fix reading of SQ with parsed VR of UN
                        if (source.Position > last || this.length == 0)
                        {
                            return true;
                        }

                        this.parseStage = ParseStage.Value;
                        this._vr = parsedVR;
                    }

                    if (this.length == UndefinedLength)
                    {
                        this.observer.OnBeginFragmentSequence(source, this._tag, this._vr);
                        this.parseStage = ParseStage.Tag;
                        await this.ParseFragmentSequenceAsync(source).ConfigureAwait(false);
                        return true;
                    }

                    if (!source.Require(this.length))
                    {
                        this.result = DicomReaderResult.Suspended;
                        return false;
                    }

                    var buffer = await source.GetBufferAsync(this.length).ConfigureAwait(false);

                    if (!this._vr.IsString)
                    {
                        buffer = EndianByteBuffer.Create(buffer, source.Endian, this._vr.UnitSize);
                    }
                    this.observer.OnElement(source, this._tag, this._vr, buffer);

                    // parse private creator value and add to lookup table
                    if (this._tag.IsPrivate && this._tag.Element != 0x0000 && this._tag.Element <= 0x00ff)
                    {
                        var creator =
                            DicomEncoding.Default.GetString(buffer.Data, 0, buffer.Data.Length)
                                .TrimEnd((char)DicomVR.LO.PaddingValue);
                        var card = (uint)(this._tag.Group << 16) + this._tag.Element;

                        lock (this.locker)
                        {
                            this._private[card] = creator;
                        }
                    }

                    this.ResetState();
                }
                return true;
            }
Exemplo n.º 25
0
            private bool ParseItemSequenceTag(IByteSource source)
            {
                if (_parseStage == ParseStage.Tag)
                {
                    source.Mark();

                    if (!source.Require(8))
                    {
                        _result = DicomReaderResult.Suspended;
                        return(false);
                    }

                    var group   = source.GetUInt16();
                    var element = source.GetUInt16();

                    _tag = new DicomTag(@group, element);

                    if (_tag != DicomTag.Item && _tag != DicomTag.SequenceDelimitationItem)
                    {
                        // assume invalid sequence
                        source.Rewind();
                        if (!_implicit)
                        {
                            source.PopMilestone();
                        }
                        _observer.OnEndSequence();
                        // #565 Only reset the badPrivate sequence if we're in the correct depth
                        // This prevents prematurely resetting in case of sub-sequences contained in the bad private sequence
                        if (_badPrivateSequence && _sequenceDepth == _badPrivateSequenceDepth)
                        {
                            _isExplicitVR       = !_isExplicitVR;
                            _badPrivateSequence = false;
                        }
                        return(false);
                    }

                    _length = source.GetUInt32();

                    if (_tag == DicomTag.SequenceDelimitationItem)
                    {
                        // #64, in case explicit length has been specified despite occurrence of Sequence Delimitation Item
                        if (source.HasReachedMilestone() && source.MilestonesCount > _sequenceDepth)
                        {
                            ResetState();
                            return(true);
                        }

                        // end of sequence
                        _observer.OnEndSequence();
                        // #565 Only reset the badPrivate sequence if we're in the correct depth
                        // This prevents prematurely resetting in case of sub-sequences contained in the bad private sequence
                        if (_badPrivateSequence && _sequenceDepth == _badPrivateSequenceDepth)
                        {
                            _isExplicitVR       = !_isExplicitVR;
                            _badPrivateSequence = false;
                        }
                        ResetState();
                        return(false);
                    }

                    _parseStage = ParseStage.Value;
                }
                return(true);
            }
Exemplo n.º 26
0
Arquivo: Parser.cs Projeto: shz/pointy
        public void AddBytes(ArraySegment<byte> data)
        {
            for (int i=0; i<data.Count; i++)
            {
                // Get the current byte from the input.  This is here for DRY; you'll
                // see `b` get used a whole lot in the state machine.
                byte b = data.Array[i + data.Offset];

                // This is one hell of a monolithic parser.  You've been warned.
                switch (Stage)
                {
                    #region Error State

                    // If we had a parse error, we're done.  We'll
                    // just silently eat all bytes passed to us.
                    case ParseStage.Error:
                        return;

                    #endregion

                    #region Eat Leading CRs/LFs

                    // I guess this isn't strictly compliant with the
                    // RFC, but we're going to eat leading CRs/LFs so
                    // that telnet users or whatever can be trigger-happy
                    // with the newlines.
                    //
                    // And there was much rejoicing.

                    case ParseStage.Start:
                        if (b == 0x0D || b == 0x0A) //CR, LF
                            break;
                        else
                            goto case ParseStage.RequestLine_StartMethod;

                    #endregion

                    #region Method Parsing

                    case ParseStage.RequestLine_StartMethod:
                        SB1.Clear();
                        Stage = ParseStage.RequestLine_Method;
                        goto case ParseStage.RequestLine_Method;
                    case ParseStage.RequestLine_Method:
                        if (b == 0x20) //Space
                        {
                            Str1 = SB1.ToString();
                            Stage = ParseStage.RequestLine_StartURI;
                        }
                        else if (b < 0x41 || b > 0x5A) // 'A' <= b <= 'Z'
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        else
                        {
                            SB1.Append((char)b);
                        }
                        break;

                    #endregion

                    #region Request URI Parsing

                    case ParseStage.RequestLine_StartURI:
                        if (b == 0x20 || b == 0x09 || b == 0x0D || b == 0x0A) //Space, horizontal tab, CR, LF
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        else
                        {
                            SB1.Clear();
                            SB1.Append((char)b);
                        }
                        Stage = ParseStage.RequestLine_URI;
                        break;

                    case ParseStage.RequestLine_URI:
                        if (b == 0x20) //Space
                        {
                            Stage = ParseStage.RequestLine_StartVersion;
                        }
                        else if (b == 0x09 || b == 0x0D || b == 0x0A) //Horizontal tab, CR, LF
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        else
                        {
                            SB1.Append((char)b);

                            // Make sure the URI isn't ridiculously long.  This also serves
                            // as a mechanism for ensuring a malformed request won't cause
                            // the parser to endlessly consume additional data from the client.
                            //
                            // I'm using another variable rather than the StringBuilder's length
                            // because I figure 4 bytes is worth the tiny (if anything) performance
                            // increase.  Probably should have done some profiling before doing this...
                            if (++Size1 > 4096)
                            {
                                EmitParseError(Error.UriTooLong);
                                return;
                            }
                        }
                        break;

                    #endregion

                    #region HTTP Version Parsing

                    case ParseStage.RequestLine_StartVersion:
                        if (b == 0x48) //H
                        {
                            Stage = ParseStage.RequestLine_H;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;
                    case ParseStage.RequestLine_H:
                        if (b == 0x54) //T
                        {
                            Stage = ParseStage.RequestLine_HT;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;
                    case ParseStage.RequestLine_HT:
                        if (b == 0x54) //T
                        {
                            Stage = ParseStage.RequestLine_HTT;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;
                    case ParseStage.RequestLine_HTT:
                        if (b == 0x50) //P
                        {
                            Stage = ParseStage.RequestLine_HTTP;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;
                    case ParseStage.RequestLine_HTTP:
                        if (b == 0x2F) // /
                        {
                            Stage = ParseStage.RequestLine_VersionMajor;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;
                    case ParseStage.RequestLine_VersionMajor:
                        if (b == 0x31) //1
                        {
                            Stage = ParseStage.RequestLine_VersionDot;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;
                    case ParseStage.RequestLine_VersionDot:
                        if (b == 0x2E) //.
                        {
                            Stage = ParseStage.RequestLine_VersionMinor;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;
                    case ParseStage.RequestLine_VersionMinor:
                        Size1 = 0;
                        if (b == 0x31) //1
                        {
                            Version = HTTP.Version.HTTP1_1;
                            Stage = ParseStage.RequestLine_EndVersion;
                        }
                        else if (b == 0x30) //0
                        {
                            Version = HTTP.Version.HTTP1_0;
                            Stage = ParseStage.RequestLine_EndVersion;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;

                    // Look for a CRLF | LF to signal the end of the request line
                    case ParseStage.RequestLine_EndVersion:
                        if (b == 0x0D) // CR
                        {
                            if (Size1 == 0)
                            {
                                Size1++;
                                break;
                            }
                            else
                            {
                                EmitParseError(Error.BadRequest);
                                return;
                            }
                        }
                        else if (b == 0x0A) // LF
                        {
                            EmitRequestLine(Str1, SB1.ToString(), Version);
                            Stage = ParseStage.Headers_Start;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;

                    #endregion

                    #region Header Parsing

                    case ParseStage.Headers_Start:
                        SB1.Clear();
                        if (b == 0x0D) //CR
                        {
                            Stage = ParseStage.Headers_AlmostEnd;
                        }
                        // We allow the headers section to end with just an LF, which
                        // is more flexible than the spec.
                        else if (b == 0x0A)
                        {
                            goto case ParseStage.Headers_AlmostEnd;
                        }
                        else
                        {
                            Stage = ParseStage.Header_Name;
                            goto case ParseStage.Header_Name;
                        }
                        break;
                    case ParseStage.Header_Name:
                        // If we hit the colon, push the stringbuilder's state
                        // into the string, so that we can build the value
                        if (b == 0x3A) // :
                        {
                            // First, make sure there's actually something
                            // in the header name.
                            if (SB1.Length == 0)
                            {
                                EmitParseError(Error.BadRequest);
                                return;
                            }

                            // Store the header name and prepare to parse
                            // the value.
                            Str1 = SB1.ToString();
                            SB1.Clear();
                            Stage = ParseStage.Header_ValueStart;
                        }
                        // Look for invalid characters
                        else if (b > 126 // DEL or Non-ASCII
                             ||  b < 33  // Space or CTL
                             ||  false)  // Theoretically, we could be more precise, but it
                                         // doesn't really seem worth spending time on.
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        else
                        {
                            SB1.Append((char)b);

                            // Limit header name size to a maximum of 128 characters
                            if (SB1.Length > 128)
                            {
                                EmitParseError(Error.HeaderFieldsTooLarge);
                                return;
                            }
                        }
                        break;
                    case ParseStage.Header_ValueStart:
                        if (b != 0x20 && b != 0x09) //Space, HTab
                        {
                            Size1 = 0;
                            Stage = ParseStage.Header_Value;
                            goto case ParseStage.Header_Value;
                        }
                        else
                        {
                            break;
                        }

                    case ParseStage.Header_Value:
                        if (b == 0x0D) //CR
                        {
                            Stage = ParseStage.Header_AlmostNewLine;
                        }
                        // We allow headers to end with LF, which is more flexible
                        // than the spec.
                        else if (b == 0x0A) // LF
                        {
                            goto case ParseStage.Header_AlmostNewLine;
                        }
                        else
                        {
                            SB1.Append((char)b);

                            // Limit header value size to 4096 characters
                            if (SB1.Length > 4096)
                            {
                                EmitParseError(Error.HeaderFieldsTooLarge, Str1);
                                return;
                            }
                        }
                        break;
                    case ParseStage.Header_AlmostNewLine:
                        if (b == 0x0A) //LF
                        {
                            Stage = ParseStage.Header_NewLine;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;
                    case ParseStage.Header_NewLine:

                        // Look for the header continuing on the next line.  If the
                        // first character is whitespace, then it's a continuation
                        // and we handle that by adding a ", " to the header's value
                        // and then just appending whatever the value contained in the
                        // header line is.
                        if (b == 0x20 || b == 0x09) //Space, HTab
                        {
                            Stage = ParseStage.Header_Value;
                            SB1.Append(", ");
                        }
                        // If it's anything but whitespace, then the header value is
                        // done, so we can emit it and continue parsing.
                        else
                        {
                            // Emit the header
                            EmitHeader(Str1, SB1.ToString());

                            // Clean up after ourselves
                            SB1.Clear();

                            // Cap the number of headers at 128
                            if (++Size1 > 128)
                            {
                                EmitParseError(Error.HeaderFieldsTooLarge);
                                return;
                            }

                            // If it's a CR, then we're ending headers.
                            if (b == 0x0D) // CR
                            {
                                Stage = ParseStage.Headers_AlmostEnd;
                            }
                            // If it's an LF, then the client just skipped
                            // the CR, and we can handle that gracefully.
                            else if (b == 0x0A)
                            {
                                Stage = ParseStage.Headers_AlmostEnd;
                                goto case ParseStage.Headers_AlmostEnd;
                            }
                            // Otherwise, it's a regular old header and we should
                            // continue parsing it.
                            else
                            {
                                Stage = ParseStage.Header_Name;
                                goto case ParseStage.Header_Name;
                            }
                        }
                        break;
                    case ParseStage.Headers_AlmostEnd:
                        if (b == 0x0A) //LF
                        {
                            if (InTrailers)
                                Stage = ParseStage.Done;
                            else
                                EmitEndHeaders();

                            // Check to see if we should expect a body
                            if (Entity == EntityType.Identity)
                            {
                                // If the size is zero, the body is over
                                if (EntitySize == 0)
                                    Stage = ParseStage.Done;
                                // Otherwise, we've got a flat body
                                else
                                    Stage = ParseStage.EntityFlat;
                            }
                            else if (Entity == EntityType.Chunked)
                            {
                                Stage = ParseStage.EntityChunked_StartChunk;
                            }
                            else
                            {
                                Stage = ParseStage.Done;
                                goto case ParseStage.Done;
                            }
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;

                    #endregion

                    #region Entity Parsing

                    #region Flat
                    case ParseStage.EntityFlat:
                        if (EntitySize > data.Count - i) //there's more data coming in the next buffer
                        {
                            //read to the end of the buffer
                            EmitBody(new ArraySegment<byte>(data.Array, i + data.Offset, data.Count - i));
                            //decrease the remaining byte count
                            EntitySize -= data.Count - i;
                            //force the loop to end
                            i = data.Count;
                        }
                        else //the current buffer contains all the data we need
                        {
                            EmitBody(new ArraySegment<byte>(data.Array, i + data.Offset, EntitySize));
                            i += EntitySize;
                            Stage = ParseStage.Done;
                            goto case ParseStage.Done;
                        }

                        break;
                    #endregion

                    #region Chunked

                    case ParseStage.EntityChunked_StartChunk:
                        SB1.Clear();
                        Stage = ParseStage.EntityChunked_ChunkSize;
                        goto case ParseStage.EntityChunked_ChunkSize;
                    case ParseStage.EntityChunked_ChunkSize:
                        if (b == 0x0D) //CR
                            Stage = ParseStage.EntityChunked_ChunkSizeCR;
                        else if (b == 0x0A) // LF
                            goto case ParseStage.EntityChunked_ChunkSizeCR;
                        else
                            SB1.Append((char)b);
                        break;

                    case ParseStage.EntityChunked_ChunkSizeCR:
                        if (b == 0x0A) //LF
                        {
                            if (!int.TryParse(SB1.ToString().Split(';')[0], System.Globalization.NumberStyles.HexNumber, System.Globalization.NumberFormatInfo.InvariantInfo, out Size1))
                            {
                                EmitParseError(Error.BadRequest);
                                return;
                            }

                            // Handle the final chunk (specified by size of 0)
                            if (Size1 == 0)
                            {
                                InTrailers = true;
                                Stage = ParseStage.Headers_Start;
                            }
                            // Carry on
                            else
                            {
                                Stage = ParseStage.EntityChunked_Chunk;
                            }
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;

                    case ParseStage.EntityChunked_Chunk:
                        if (Size1 > data.Count - i) //there's more data coming in the next buffer
                        {
                            //read to the end of the buffer
                            EmitBody(new ArraySegment<byte>(data.Array, i + data.Offset, data.Count - i));
                            //decrease the remaining byte count
                            Size1 -= data.Count - i;
                        }
                        else //the current buffer contains all the data we need
                        {
                            EmitBody(new ArraySegment<byte>(data.Array, i + data.Offset, Size1));
                            i += Size1 - 1;
                            Stage = ParseStage.EntityChunked_ChunkEnd;
                        }
                        break;

                    case ParseStage.EntityChunked_ChunkEnd:
                        if (b == 0x0D) // CR
                        {
                            Stage = ParseStage.EntityChunked_ChunkCR;
                        }
                        else if (b == 0x0A) // LF
                        {
                            goto case ParseStage.EntityChunked_ChunkCR;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;
                    case ParseStage.EntityChunked_ChunkCR:
                        if (b == 0x0A) //LF
                        {
                            Stage = ParseStage.EntityChunked_StartChunk;
                        }
                        else
                        {
                            EmitParseError(Error.BadRequest);
                            return;
                        }
                        break;

                    #endregion

                    #endregion

                    // If we're done, wrap things up and keep on truckin'
                    case ParseStage.Done:

                        // Finish up the request
                        EmitEnd();

                        // Reset some state
                        Entity = EntityType.None;

                        // Go back to the start, which lets us handle more data on this
                        // packet.
                        Stage = ParseStage.Start;
                        break;
                }
            }
        }