private void GotData(XmlParserResult data) { bool lStopReading = false; switch (data.Type) { case XmlParserResultType.Error: SendStreamError(new StreamError { Error = ((XmlErrorResult)data).Error }); return; case XmlParserResultType.Node: XmlNodeResult nd = (XmlNodeResult)data; switch (nd.NodeType) { case XmlNodeType.XmlInfo: break; // who cares about that? case XmlNodeType.Single: if (fServerElementStack.Count == 0) { SendStreamError(new StreamError { Error = StreamErrorKind.InvalidXml }); return; } Element el = CreateNode(nd, fServerElementStack[fServerElementStack.Count - 1]); if (this.fServerElementStack.Count <= 1) lStopReading = GotFirstLevelElement(el); break; case XmlNodeType.Open: el = CreateNode(nd, fServerElementStack.Count == 0 ? null : fServerElementStack[fServerElementStack.Count - 1]); this.fServerElementStack.Add(el); if (this.fServerElementStack.Count == 1) GotRootLevelElement(el); break; case XmlNodeType.Close: if (fServerElementStack.Count == 0 || !fServerElementStack[fServerElementStack.Count - 1].Matches(nd.Prefix, nd.Name)) { SendStreamError(new StreamError { Error = StreamErrorKind.InvalidXml }); return; } el = fServerElementStack[fServerElementStack.Count - 1]; fServerElementStack.RemoveAt(fServerElementStack.Count - 1); if (fServerElementStack.Count == 0) { Close(); break; } if (fServerElementStack.Count == 1) { lStopReading = GotFirstLevelElement(el); } break; } break; case XmlParserResultType.Text: if (fServerElementStack.Count == 0) { // discard } else { fServerElementStack[fServerElementStack.Count - 1].Text += ((XmlTextResult)data).Text; } break; } if (!lStopReading) parser.ReadXmlElementAsync(new Action<XmlParserResult>(GotData), fServerElementStack.Count > 0); }
private void Read() { try { switch (state) { case AsyncState.AllowText: state = AsyncState.GotAllowText; if (BeginReadUntil(a => a == '<', true)) { goto case AsyncState.GotAllowText; } return; case AsyncState.GotAllowText: if (this.currentData.Length > 0) { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(UnEscape(Encoding.UTF8.GetString(this.currentData.GetBuffer(), 0, (int)currentData.Length)))); return; } goto case AsyncState.GotStartByte; case AsyncState.None: state = AsyncState.GotStartByte; if (BeginReadUntil(a => true, false)) // read until we've got something { goto case AsyncState.GotStartByte; } return; case AsyncState.GotStartByte: if (ReadByte() != '<') { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); return; } state = AsyncState.GotSecondByte; if (BeginReadUntil(a => true, false)) { goto case AsyncState.GotSecondByte; } return; case AsyncState.GotSecondByte: currentData.SetLength(0); int n = ReadByte(); switch (n) { case '?': currentNodeType = XmlNodeType.XmlInfo; break; case '/': currentNodeType = XmlNodeType.Close; break; default: currentNodeType = XmlNodeType.Open; if (ValidXmlNameChar((char)n, true)) { currentData.WriteByte((byte)n); } else { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); return; } break; } state = AsyncState.GotName; if (BeginReadUntil(a => !ValidXmlNameChar((char)a, currentData.Length == 0), false)) { goto case AsyncState.GotName; } return; case AsyncState.GotName: name = Encoding.UTF8.GetString(this.currentData.GetBuffer(), 0, (int)currentData.Length); attributes.Clear(); goto case AsyncState.SkipWhitespace; case AsyncState.SkipWhitespace: state = AsyncState.AfterWhitespaceInElement; if (BeginReadUntil(a => !(a == '\r' || a == '\n' || a == ' ' || a == '\t'), true)) { goto case AsyncState.AfterWhitespaceInElement; } return; case AsyncState.AfterWhitespaceInElement: n = ReadByte(); if (n == '/') { if (currentNodeType != XmlNodeType.Open) { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); return; } currentNodeType = XmlNodeType.Single; state = AsyncState.WantClosingTag; if (BeginReadUntil(a => true, false)) { goto case AsyncState.WantClosingTag; } return; } else if (n == '?') { if (currentNodeType != XmlNodeType.XmlInfo) { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); return; } state = AsyncState.WantClosingTag; if (BeginReadUntil(a => true, false)) { goto case AsyncState.WantClosingTag; } return; } else if (n == '>') { if (currentNodeType == XmlNodeType.XmlInfo) { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); return; } state = AsyncState.None; gotResultCallback(XmlParserResult.Create(currentNodeType, name, attributes)); return; } // attribute: if (ValidXmlNameChar((char)n, true)) { currentData.SetLength(0); currentData.WriteByte((byte)n); state = AsyncState.ReadAttributeName; if (BeginReadUntil(a => !ValidXmlNameChar((char)a, false), false)) { goto case AsyncState.ReadAttributeName; } } else { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); } return; case AsyncState.WantClosingTag: if (ReadByte() != '>') { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); return; } state = AsyncState.None; gotResultCallback(XmlParserResult.Create(currentNodeType, name, attributes)); return; case AsyncState.ReadAttributeName: currattname = Encoding.UTF8.GetString(this.currentData.GetBuffer(), 0, (int)currentData.Length); state = AsyncState.AfterWhitespaceInAttributeBeforeEqual; if (BeginReadUntil(a => !(a == '\r' || a == '\n' || a == ' ' || a == '\t'), true)) { goto case AsyncState.AfterWhitespaceInAttributeBeforeEqual; } return; case AsyncState.AfterWhitespaceInAttributeBeforeEqual: if (ReadByte() != '=') { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); return; } state = AsyncState.AfterWhitespaceInAttributeAfterEqual; if (BeginReadUntil(a => !(a == '\r' || a == '\n' || a == ' ' || a == '\t'), true)) { goto case AsyncState.AfterWhitespaceInAttributeAfterEqual; } return; case AsyncState.AfterWhitespaceInAttributeAfterEqual: n = ReadByte(); if (n == '"') { state = AsyncState.ReadStringDoubleQuote; if (BeginReadUntil(a => a == '"', true)) { goto case AsyncState.ReadStringDoubleQuote; } } else if (n == '\'') { state = AsyncState.ReadStringSingleQuote; if (BeginReadUntil(a => a == '\'', true)) { goto case AsyncState.ReadStringSingleQuote; } } else { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); } return; case AsyncState.ReadStringDoubleQuote: case AsyncState.ReadStringSingleQuote: ReadByte(); // we don't do anything with this attributes.Add(ParseAttribute(currattname, Encoding.UTF8.GetString(this.currentData.GetBuffer(), 0, (int)currentData.Length))); goto case AsyncState.SkipWhitespace; default: state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); // shouldn't happen return; } } catch { state = AsyncState.None; gotResultCallback(XmlParserResult.Create(StreamErrorKind.InvalidXml)); return; } }