Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / Documents / XamlToRtfParser.cs / 1 / XamlToRtfParser.cs
//---------------------------------------------------------------------------- // // File: XamlToRtfParser.cs // // Copyright (C) Microsoft Corporation. All rights reserved. // // Description: Xaml parser to convert the xaml content into Rtf content. // //--------------------------------------------------------------------------- using System.Collections; namespace System.Windows.Documents { ////// Xaml parser to convert the xaml content into Rtf content. /// internal class XamlToRtfParser { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors ////// XamlToRtfParser constructor /// internal XamlToRtfParser(string xaml) { _xaml = xaml; _xamlLexer = new XamlLexer(_xaml); _xamlTagStack = new XamlTagStack(); _xamlAttributes = new XamlAttributes(_xaml); } #endregion Constructors // ---------------------------------------------------------------------- // // internal Methods // // --------------------------------------------------------------------- #region internal Methods internal XamlToRtfError Parse() { // Need callbacks if (_xamlContent == null || _xamlError == null) { return XamlToRtfError.Unknown; } // We are simply looking for well-formedness: that is, that the XML is lexically valid and tags are balanced. XamlToRtfError xamlToRtfError = XamlToRtfError.None; XamlToken xamlToken = new XamlToken(); string name = string.Empty; // Fire things off xamlToRtfError = _xamlContent.StartDocument(); while (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = _xamlLexer.Next(xamlToken); if (xamlToRtfError != XamlToRtfError.None || xamlToken.TokenType == XamlTokenType.XTokEOF) { break; } switch (xamlToken.TokenType) { case XamlTokenType.XTokInvalid: xamlToRtfError = XamlToRtfError.Unknown; break; case XamlTokenType.XTokCharacters: xamlToRtfError = _xamlContent.Characters(xamlToken.Text); break; case XamlTokenType.XTokEntity: xamlToRtfError = _xamlContent.SkippedEntity(xamlToken.Text); break; case XamlTokenType.XTokStartElement: xamlToRtfError = ParseXTokStartElement(xamlToken, ref name); break; case XamlTokenType.XTokEndElement: xamlToRtfError = ParseXTokEndElement(xamlToken, ref name); break; case XamlTokenType.XTokCData: // Ignore break; case XamlTokenType.XTokPI: // Ignore break; case XamlTokenType.XTokComment: // Ignore break; case XamlTokenType.XTokWS: xamlToRtfError = _xamlContent.IgnorableWhitespace(xamlToken.Text); break; default: xamlToRtfError = XamlToRtfError.Unknown; break; } } // All tags need to have been popped. if (xamlToRtfError == XamlToRtfError.None && _xamlTagStack.Count != 0) { xamlToRtfError = XamlToRtfError.Unknown; } // Wrap things up if (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = _xamlContent.EndDocument(); } return xamlToRtfError; } internal void SetCallbacks(IXamlContentHandler xamlContent, IXamlErrorHandler xamlError) { _xamlContent = xamlContent; _xamlError = xamlError; } #endregion internal Methods // ---------------------------------------------------------------------- // // internal Properties // // ---------------------------------------------------------------------- #region internal Properties #endregion internal Properties // --------------------------------------------------------------------- // // Private Methods // // ---------------------------------------------------------------------- #region Private Methods // Helper for Parse method. private XamlToRtfError ParseXTokStartElement(XamlToken xamlToken, ref string name) { XamlToRtfError xamlToRtfError = _xamlAttributes.Init(xamlToken.Text); if (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = _xamlAttributes.GetTag(ref name); if (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = _xamlContent.StartElement(string.Empty, name, name, _xamlAttributes); if (xamlToRtfError == XamlToRtfError.None) { if (_xamlAttributes.IsEmpty) { xamlToRtfError = _xamlContent.EndElement(string.Empty, name, name); } else { xamlToRtfError = (XamlToRtfError)_xamlTagStack.Push(name); } } } } return xamlToRtfError; } // Helper for Parse method. private XamlToRtfError ParseXTokEndElement(XamlToken xamlToken, ref string name) { XamlToRtfError xamlToRtfError = _xamlAttributes.Init(xamlToken.Text); if (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = _xamlAttributes.GetTag(ref name); if (xamlToRtfError == XamlToRtfError.None) { if (_xamlTagStack.IsMatchTop(name)) { _xamlTagStack.Pop(); xamlToRtfError = _xamlContent.EndElement(string.Empty, name, name); } } } return xamlToRtfError; } #endregion Private Methods // --------------------------------------------------------------------- // // Private Fields // // --------------------------------------------------------------------- #region Private Fields private string _xaml; private XamlLexer _xamlLexer; private XamlTagStack _xamlTagStack; private XamlAttributes _xamlAttributes; private IXamlContentHandler _xamlContent; private IXamlErrorHandler _xamlError; #endregion Private Fields // --------------------------------------------------------------------- // // Internal Class // // ---------------------------------------------------------------------- #region Internal Class internal class XamlLexer { //----------------------------------------------------- // // Constructors // //------------------------------------------------------ #region Constructors ////// /// internal XamlLexer(string xaml) { _xaml = xaml; } #endregion Constructors // ---------------------------------------------------------------------- // // internal Methods // // --------------------------------------------------------------------- #region internal Methods internal XamlToRtfError Next(XamlToken token) { XamlToRtfError xamlToRtfError = XamlToRtfError.None; int startIndex = _xamlIndex; if (_xamlIndex < _xaml.Length) { char tokenChar = _xaml[_xamlIndex]; switch (tokenChar) { case ' ': case '\t': case '\r': case '\n': token.TokenType = XamlTokenType.XTokWS; for (_xamlIndex++; IsCharsAvailable(1) && IsSpace(_xaml[_xamlIndex]); _xamlIndex++) { continue; } break; case '<': NextLessThanToken(token); break; case '&': // Entity token.TokenType = XamlTokenType.XTokInvalid; for (_xamlIndex++; IsCharsAvailable(1); _xamlIndex++) { if (_xaml[_xamlIndex] == ';') { _xamlIndex++; token.TokenType = XamlTokenType.XTokEntity; break; } } break; default: // Plain text token.TokenType = XamlTokenType.XTokCharacters; for (_xamlIndex++; IsCharsAvailable(1); _xamlIndex++) { if (_xaml[_xamlIndex] == '&' || _xaml[_xamlIndex] == '<') { break; } } break; } } token.Text = _xaml.Substring(startIndex, _xamlIndex - startIndex); if (token.Text.Length == 0) { token.TokenType = XamlTokenType.XTokEOF; } return xamlToRtfError; } #endregion internal Methods #region Private Methods // ---------------------------------------------------------------------- // // Private Methods // // --------------------------------------------------------------------- private bool IsSpace(char character) { return (character == ' ' || character == '\t' || character == '\n' || character == '\r'); } private bool IsCharsAvailable(int index) { return ((_xamlIndex + index) <= _xaml.Length); } // Helper for the Next method, handles '<' token. private void NextLessThanToken(XamlToken token) { _xamlIndex++; // Careful... if (!IsCharsAvailable(1)) { token.TokenType = XamlTokenType.XTokInvalid; return; } // Default is we're going to see an invalid sequence token.TokenType = XamlTokenType.XTokInvalid; char currentChar = _xaml[_xamlIndex]; switch (currentChar) { case '?': // Processing Instruction for (_xamlIndex++; IsCharsAvailable(2); _xamlIndex++) { if (_xaml[_xamlIndex] == '?' && _xaml[_xamlIndex + 1] == '>') { _xamlIndex += 2; token.TokenType = XamlTokenType.XTokPI; break; } } break; case '!': // Comment - _xamlIndex++; for (; IsCharsAvailable(3); _xamlIndex++) { if (_xaml[_xamlIndex] == '-' && _xaml[_xamlIndex + 1] == '-' && _xaml[_xamlIndex + 2] == '>') { _xamlIndex += 3; token.TokenType = XamlTokenType.XTokComment; break; } } break; case '>': // Anomaly _xamlIndex++; token.TokenType = XamlTokenType.XTokInvalid; break; case '/': // End Element for (_xamlIndex++; IsCharsAvailable(1); _xamlIndex++) { if (_xaml[_xamlIndex] == '>') { _xamlIndex++; token.TokenType = XamlTokenType.XTokEndElement; break; } } break; default: // Start Element // Tricky element here is making sure we correctly parse quoted strings so that we don't // incorrectly treat a '>' in a string as ending the token. { char quoteChar = (char)0x00; for (; IsCharsAvailable(1); _xamlIndex++) { if (quoteChar != 0x00) { if (_xaml[_xamlIndex] == quoteChar) { quoteChar = (char)0x00; } } else if (_xaml[_xamlIndex] == '"' || _xaml[_xamlIndex] == '\'') { quoteChar = _xaml[_xamlIndex]; } else if (_xaml[_xamlIndex] == '>') { _xamlIndex++; token.TokenType = XamlTokenType.XTokStartElement; break; } } } break; } } #endregion Private Methods //----------------------------------------------------- // // Private Fields // //----------------------------------------------------- #region Private Fields private string _xaml; private int _xamlIndex; #endregion Private Fields } internal class XamlTagStack : ArrayList { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors ////// /// internal XamlTagStack() : base(10) { } #endregion Constructors // ---------------------------------------------------------------------- // // internal Methods // // ---------------------------------------------------------------------- #region internal Methods internal RtfToXamlError Push(string xamlTag) { Add(xamlTag); return RtfToXamlError.None; } internal void Pop() { if (Count > 0) { RemoveAt(Count - 1); } } internal bool IsMatchTop(string xamlTag) { if (Count == 0) { return false; } string top = (string)this[Count - 1]; if (top.Length == 0) { return false; } if (string.Compare(xamlTag, xamlTag.Length, top, top.Length, top.Length, StringComparison.OrdinalIgnoreCase) == 0) { return true; } else { return false; } } #endregion internal Methods } internal class XamlAttributes : IXamlAttributes { //----------------------------------------------------- // // Constructors // //------------------------------------------------------ #region Constructors ////// /// internal XamlAttributes(string xaml) { _xamlParsePoints = new XamlParsePoints(); } #endregion Constructors //----------------------------------------------------- // // internal Methods // //----------------------------------------------------- #region internal Methods internal XamlToRtfError Init(string xaml) { return _xamlParsePoints.Init(xaml); } internal XamlToRtfError GetTag(ref string xamlTag) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; if (!_xamlParsePoints.IsValid) { return XamlToRtfError.Unknown; } xamlTag = (string)_xamlParsePoints[0]; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetLength(ref int length) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; if (_xamlParsePoints.IsValid) { length = (_xamlParsePoints.Count - 1) / 2; return rtfToXamlError; } else { return XamlToRtfError.Unknown; } } XamlToRtfError IXamlAttributes.GetUri(int index, ref string uri) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetLocalName(int index, ref string localName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetQName(int index, ref string qName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetName(int index, ref string uri, ref string localName, ref string qName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; int nLength = (_xamlParsePoints.Count - 1) / 2; if (index < 0 || index > nLength - 1) { return XamlToRtfError.Unknown; } localName = (string)_xamlParsePoints[index * 2 + 1]; qName = (string)_xamlParsePoints[index * 2 + 2]; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetIndexFromName(string uri, string localName, ref int index) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetIndexFromQName(string qName, ref int index) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetType(int index, ref string typeName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetTypeFromName(string uri, string localName, ref string typeName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetValue(int index, ref string valueName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; int nLength = (_xamlParsePoints.Count - 1) / 2; if (index < 0 || index > nLength - 1) { return XamlToRtfError.OutOfRange; } valueName = (string)_xamlParsePoints[index * 2 + 2]; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetValueFromName(string uri, string localName, ref string valueName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetValueFromQName(string qName, ref string valueName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetTypeFromQName(string qName, ref string typeName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } #endregion internal Methods #region internal Properties //----------------------------------------------------- // // internal Properties // //------------------------------------------------------ internal bool IsEmpty { get { return _xamlParsePoints.IsEmpty; } } #endregion internal Properties //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields private XamlParsePoints _xamlParsePoints; #endregion Private Fields } internal class XamlParsePoints : ArrayList { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors ////// /// internal XamlParsePoints() : base(10) { } #endregion Constructors // ---------------------------------------------------------------------- // // internal Methods // // --------------------------------------------------------------------- #region internal Methods internal XamlToRtfError Init(string xaml) { XamlToRtfError xamlToRtfError = XamlToRtfError.None; // Initialize _empty = false; _valid = false; Clear(); char quoteChar; int xamlIndex = 0; // Need to have at least "<...>". Note that verification at this point that the string ends with angle // bracket allows me below to safely loop looking for specific character sets that don't match angle bracket // without also explicitly having to test for looping past the end of the string. if (xaml.Length < 2 || xaml[0] != '<' || xaml[xaml.Length - 1] != '>') { return XamlToRtfError.Unknown; } xamlIndex++; if (IsSpace(xaml[xamlIndex])) { return XamlToRtfError.Unknown; } // An end tag? if (xaml[xamlIndex] == '/') { return HandleEndTag(xaml, xamlIndex); } // Add the start and end of the tag pointers //AddParseData(xaml.Substring(xamlIndex)); int startIndex = xamlIndex; // Note that check above that the string ends in angle simplifies loop check for (xamlIndex++; IsNameChar(xaml[xamlIndex]); xamlIndex++) { continue; } AddParseData(xaml.Substring(startIndex, xamlIndex - startIndex)); // Start parsing name/value pairs while (xamlIndex < xaml.Length) { // Move past spaces for (; IsSpace(xaml[xamlIndex]); xamlIndex++) { continue; } // Done? if (xamlIndex == xaml.Length - 1) { break; } // Empty tag? if (xaml[xamlIndex] == '/') { if (xamlIndex == xaml.Length - 2) { _empty = true; break; } else { return XamlToRtfError.Unknown; } } // OK, have another attribute //AddParseData(xaml.Substring(xamlIndex)); startIndex = xamlIndex; for (xamlIndex++; IsNameChar(xaml[xamlIndex]); xamlIndex++) { continue; } AddParseData(xaml.Substring(startIndex, xamlIndex - startIndex)); // Move past optional trailing spaces if (xamlIndex < xaml.Length) { for (; IsSpace(xaml[xamlIndex]); xamlIndex++) { continue; } } // Attribute with no '='? if (xamlIndex == xaml.Length || xaml[xamlIndex] != '=') { return XamlToRtfError.Unknown; } // Move past '=' and optional trailing spaces xamlIndex++; for (; IsSpace(xaml[xamlIndex]); xamlIndex++) { continue; } // Value needs to be quoted if (xaml[xamlIndex] != '\'' && xaml[xamlIndex] != '"') { return XamlToRtfError.Unknown; } quoteChar = xaml[xamlIndex++]; //AddParseData(xaml.Substring(xamlIndex)); startIndex = xamlIndex; for (; xamlIndex < xaml.Length && xaml[xamlIndex] != quoteChar; xamlIndex++) { continue; } if (xamlIndex == xaml.Length) { return XamlToRtfError.Unknown; } AddParseData(xaml.Substring(startIndex, xamlIndex - startIndex)); xamlIndex++; } _valid = true; return xamlToRtfError; } internal void AddParseData(string parseData) { Add(parseData); } #endregion internal Methods // --------------------------------------------------------------------- // // internal Properties // // --------------------------------------------------------------------- #region internal Properties internal bool IsEmpty { get { return _empty; } } internal bool IsValid { get { return _valid; } } #endregion internal Properties #region Private Methods // ---------------------------------------------------------------------- // // Private Methods // // --------------------------------------------------------------------- private bool IsSpace(char character) { return (character == ' ' || character == '\t' || character == '\n' || character == '\r'); } private bool IsNameChar(char character) { return (!IsSpace(character) && character != '=' && character != '>' && character != '/'); } // Helper for Init method. private XamlToRtfError HandleEndTag(string xaml, int xamlIndex) { xamlIndex++; // Move past spaces for (; IsSpace(xaml[xamlIndex]); xamlIndex++) { continue; } // At name start int startIndex = xamlIndex; // Move past name for (xamlIndex++; IsNameChar(xaml[xamlIndex]); xamlIndex++) { continue; } AddParseData(xaml.Substring(startIndex, xamlIndex - startIndex)); // Move past spaces for (; IsSpace(xaml[xamlIndex]); xamlIndex++) { continue; } // Now must be at end of token if (xamlIndex == xaml.Length - 1) { _valid = true; return XamlToRtfError.None; } return XamlToRtfError.Unknown; } #endregion Private Methods // ---------------------------------------------------------------------- // // Private Fields // // ---------------------------------------------------------------------- #region Private Fields private bool _empty; private bool _valid; #endregion Private Fields } internal class XamlToken { //----------------------------------------------------- // // Constructors // //------------------------------------------------------ #region Constructors ////// /// internal XamlToken() { } #endregion Constructors // --------------------------------------------------------------------- // // internal Properties // // --------------------------------------------------------------------- #region internal Properties internal XamlTokenType TokenType { get { return _tokenType; } set { _tokenType = value; } } internal string Text { get { return _text; } set { _text = value; } } #endregion internal Properties // --------------------------------------------------------------------- // // Private Fields // // ---------------------------------------------------------------------- #region Private Fields private XamlTokenType _tokenType; private string _text; #endregion Private Fields } #endregion Private Class } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // File: XamlToRtfParser.cs // // Copyright (C) Microsoft Corporation. All rights reserved. // // Description: Xaml parser to convert the xaml content into Rtf content. // //--------------------------------------------------------------------------- using System.Collections; namespace System.Windows.Documents { ////// Xaml parser to convert the xaml content into Rtf content. /// internal class XamlToRtfParser { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors ////// XamlToRtfParser constructor /// internal XamlToRtfParser(string xaml) { _xaml = xaml; _xamlLexer = new XamlLexer(_xaml); _xamlTagStack = new XamlTagStack(); _xamlAttributes = new XamlAttributes(_xaml); } #endregion Constructors // ---------------------------------------------------------------------- // // internal Methods // // --------------------------------------------------------------------- #region internal Methods internal XamlToRtfError Parse() { // Need callbacks if (_xamlContent == null || _xamlError == null) { return XamlToRtfError.Unknown; } // We are simply looking for well-formedness: that is, that the XML is lexically valid and tags are balanced. XamlToRtfError xamlToRtfError = XamlToRtfError.None; XamlToken xamlToken = new XamlToken(); string name = string.Empty; // Fire things off xamlToRtfError = _xamlContent.StartDocument(); while (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = _xamlLexer.Next(xamlToken); if (xamlToRtfError != XamlToRtfError.None || xamlToken.TokenType == XamlTokenType.XTokEOF) { break; } switch (xamlToken.TokenType) { case XamlTokenType.XTokInvalid: xamlToRtfError = XamlToRtfError.Unknown; break; case XamlTokenType.XTokCharacters: xamlToRtfError = _xamlContent.Characters(xamlToken.Text); break; case XamlTokenType.XTokEntity: xamlToRtfError = _xamlContent.SkippedEntity(xamlToken.Text); break; case XamlTokenType.XTokStartElement: xamlToRtfError = ParseXTokStartElement(xamlToken, ref name); break; case XamlTokenType.XTokEndElement: xamlToRtfError = ParseXTokEndElement(xamlToken, ref name); break; case XamlTokenType.XTokCData: // Ignore break; case XamlTokenType.XTokPI: // Ignore break; case XamlTokenType.XTokComment: // Ignore break; case XamlTokenType.XTokWS: xamlToRtfError = _xamlContent.IgnorableWhitespace(xamlToken.Text); break; default: xamlToRtfError = XamlToRtfError.Unknown; break; } } // All tags need to have been popped. if (xamlToRtfError == XamlToRtfError.None && _xamlTagStack.Count != 0) { xamlToRtfError = XamlToRtfError.Unknown; } // Wrap things up if (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = _xamlContent.EndDocument(); } return xamlToRtfError; } internal void SetCallbacks(IXamlContentHandler xamlContent, IXamlErrorHandler xamlError) { _xamlContent = xamlContent; _xamlError = xamlError; } #endregion internal Methods // ---------------------------------------------------------------------- // // internal Properties // // ---------------------------------------------------------------------- #region internal Properties #endregion internal Properties // --------------------------------------------------------------------- // // Private Methods // // ---------------------------------------------------------------------- #region Private Methods // Helper for Parse method. private XamlToRtfError ParseXTokStartElement(XamlToken xamlToken, ref string name) { XamlToRtfError xamlToRtfError = _xamlAttributes.Init(xamlToken.Text); if (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = _xamlAttributes.GetTag(ref name); if (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = _xamlContent.StartElement(string.Empty, name, name, _xamlAttributes); if (xamlToRtfError == XamlToRtfError.None) { if (_xamlAttributes.IsEmpty) { xamlToRtfError = _xamlContent.EndElement(string.Empty, name, name); } else { xamlToRtfError = (XamlToRtfError)_xamlTagStack.Push(name); } } } } return xamlToRtfError; } // Helper for Parse method. private XamlToRtfError ParseXTokEndElement(XamlToken xamlToken, ref string name) { XamlToRtfError xamlToRtfError = _xamlAttributes.Init(xamlToken.Text); if (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = _xamlAttributes.GetTag(ref name); if (xamlToRtfError == XamlToRtfError.None) { if (_xamlTagStack.IsMatchTop(name)) { _xamlTagStack.Pop(); xamlToRtfError = _xamlContent.EndElement(string.Empty, name, name); } } } return xamlToRtfError; } #endregion Private Methods // --------------------------------------------------------------------- // // Private Fields // // --------------------------------------------------------------------- #region Private Fields private string _xaml; private XamlLexer _xamlLexer; private XamlTagStack _xamlTagStack; private XamlAttributes _xamlAttributes; private IXamlContentHandler _xamlContent; private IXamlErrorHandler _xamlError; #endregion Private Fields // --------------------------------------------------------------------- // // Internal Class // // ---------------------------------------------------------------------- #region Internal Class internal class XamlLexer { //----------------------------------------------------- // // Constructors // //------------------------------------------------------ #region Constructors ////// /// internal XamlLexer(string xaml) { _xaml = xaml; } #endregion Constructors // ---------------------------------------------------------------------- // // internal Methods // // --------------------------------------------------------------------- #region internal Methods internal XamlToRtfError Next(XamlToken token) { XamlToRtfError xamlToRtfError = XamlToRtfError.None; int startIndex = _xamlIndex; if (_xamlIndex < _xaml.Length) { char tokenChar = _xaml[_xamlIndex]; switch (tokenChar) { case ' ': case '\t': case '\r': case '\n': token.TokenType = XamlTokenType.XTokWS; for (_xamlIndex++; IsCharsAvailable(1) && IsSpace(_xaml[_xamlIndex]); _xamlIndex++) { continue; } break; case '<': NextLessThanToken(token); break; case '&': // Entity token.TokenType = XamlTokenType.XTokInvalid; for (_xamlIndex++; IsCharsAvailable(1); _xamlIndex++) { if (_xaml[_xamlIndex] == ';') { _xamlIndex++; token.TokenType = XamlTokenType.XTokEntity; break; } } break; default: // Plain text token.TokenType = XamlTokenType.XTokCharacters; for (_xamlIndex++; IsCharsAvailable(1); _xamlIndex++) { if (_xaml[_xamlIndex] == '&' || _xaml[_xamlIndex] == '<') { break; } } break; } } token.Text = _xaml.Substring(startIndex, _xamlIndex - startIndex); if (token.Text.Length == 0) { token.TokenType = XamlTokenType.XTokEOF; } return xamlToRtfError; } #endregion internal Methods #region Private Methods // ---------------------------------------------------------------------- // // Private Methods // // --------------------------------------------------------------------- private bool IsSpace(char character) { return (character == ' ' || character == '\t' || character == '\n' || character == '\r'); } private bool IsCharsAvailable(int index) { return ((_xamlIndex + index) <= _xaml.Length); } // Helper for the Next method, handles '<' token. private void NextLessThanToken(XamlToken token) { _xamlIndex++; // Careful... if (!IsCharsAvailable(1)) { token.TokenType = XamlTokenType.XTokInvalid; return; } // Default is we're going to see an invalid sequence token.TokenType = XamlTokenType.XTokInvalid; char currentChar = _xaml[_xamlIndex]; switch (currentChar) { case '?': // Processing Instruction for (_xamlIndex++; IsCharsAvailable(2); _xamlIndex++) { if (_xaml[_xamlIndex] == '?' && _xaml[_xamlIndex + 1] == '>') { _xamlIndex += 2; token.TokenType = XamlTokenType.XTokPI; break; } } break; case '!': // Comment - _xamlIndex++; for (; IsCharsAvailable(3); _xamlIndex++) { if (_xaml[_xamlIndex] == '-' && _xaml[_xamlIndex + 1] == '-' && _xaml[_xamlIndex + 2] == '>') { _xamlIndex += 3; token.TokenType = XamlTokenType.XTokComment; break; } } break; case '>': // Anomaly _xamlIndex++; token.TokenType = XamlTokenType.XTokInvalid; break; case '/': // End Element for (_xamlIndex++; IsCharsAvailable(1); _xamlIndex++) { if (_xaml[_xamlIndex] == '>') { _xamlIndex++; token.TokenType = XamlTokenType.XTokEndElement; break; } } break; default: // Start Element // Tricky element here is making sure we correctly parse quoted strings so that we don't // incorrectly treat a '>' in a string as ending the token. { char quoteChar = (char)0x00; for (; IsCharsAvailable(1); _xamlIndex++) { if (quoteChar != 0x00) { if (_xaml[_xamlIndex] == quoteChar) { quoteChar = (char)0x00; } } else if (_xaml[_xamlIndex] == '"' || _xaml[_xamlIndex] == '\'') { quoteChar = _xaml[_xamlIndex]; } else if (_xaml[_xamlIndex] == '>') { _xamlIndex++; token.TokenType = XamlTokenType.XTokStartElement; break; } } } break; } } #endregion Private Methods //----------------------------------------------------- // // Private Fields // //----------------------------------------------------- #region Private Fields private string _xaml; private int _xamlIndex; #endregion Private Fields } internal class XamlTagStack : ArrayList { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors ////// /// internal XamlTagStack() : base(10) { } #endregion Constructors // ---------------------------------------------------------------------- // // internal Methods // // ---------------------------------------------------------------------- #region internal Methods internal RtfToXamlError Push(string xamlTag) { Add(xamlTag); return RtfToXamlError.None; } internal void Pop() { if (Count > 0) { RemoveAt(Count - 1); } } internal bool IsMatchTop(string xamlTag) { if (Count == 0) { return false; } string top = (string)this[Count - 1]; if (top.Length == 0) { return false; } if (string.Compare(xamlTag, xamlTag.Length, top, top.Length, top.Length, StringComparison.OrdinalIgnoreCase) == 0) { return true; } else { return false; } } #endregion internal Methods } internal class XamlAttributes : IXamlAttributes { //----------------------------------------------------- // // Constructors // //------------------------------------------------------ #region Constructors ////// /// internal XamlAttributes(string xaml) { _xamlParsePoints = new XamlParsePoints(); } #endregion Constructors //----------------------------------------------------- // // internal Methods // //----------------------------------------------------- #region internal Methods internal XamlToRtfError Init(string xaml) { return _xamlParsePoints.Init(xaml); } internal XamlToRtfError GetTag(ref string xamlTag) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; if (!_xamlParsePoints.IsValid) { return XamlToRtfError.Unknown; } xamlTag = (string)_xamlParsePoints[0]; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetLength(ref int length) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; if (_xamlParsePoints.IsValid) { length = (_xamlParsePoints.Count - 1) / 2; return rtfToXamlError; } else { return XamlToRtfError.Unknown; } } XamlToRtfError IXamlAttributes.GetUri(int index, ref string uri) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetLocalName(int index, ref string localName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetQName(int index, ref string qName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetName(int index, ref string uri, ref string localName, ref string qName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; int nLength = (_xamlParsePoints.Count - 1) / 2; if (index < 0 || index > nLength - 1) { return XamlToRtfError.Unknown; } localName = (string)_xamlParsePoints[index * 2 + 1]; qName = (string)_xamlParsePoints[index * 2 + 2]; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetIndexFromName(string uri, string localName, ref int index) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetIndexFromQName(string qName, ref int index) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetType(int index, ref string typeName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetTypeFromName(string uri, string localName, ref string typeName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetValue(int index, ref string valueName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; int nLength = (_xamlParsePoints.Count - 1) / 2; if (index < 0 || index > nLength - 1) { return XamlToRtfError.OutOfRange; } valueName = (string)_xamlParsePoints[index * 2 + 2]; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetValueFromName(string uri, string localName, ref string valueName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetValueFromQName(string qName, ref string valueName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } XamlToRtfError IXamlAttributes.GetTypeFromQName(string qName, ref string typeName) { XamlToRtfError rtfToXamlError = XamlToRtfError.None; return rtfToXamlError; } #endregion internal Methods #region internal Properties //----------------------------------------------------- // // internal Properties // //------------------------------------------------------ internal bool IsEmpty { get { return _xamlParsePoints.IsEmpty; } } #endregion internal Properties //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields private XamlParsePoints _xamlParsePoints; #endregion Private Fields } internal class XamlParsePoints : ArrayList { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors ////// /// internal XamlParsePoints() : base(10) { } #endregion Constructors // ---------------------------------------------------------------------- // // internal Methods // // --------------------------------------------------------------------- #region internal Methods internal XamlToRtfError Init(string xaml) { XamlToRtfError xamlToRtfError = XamlToRtfError.None; // Initialize _empty = false; _valid = false; Clear(); char quoteChar; int xamlIndex = 0; // Need to have at least "<...>". Note that verification at this point that the string ends with angle // bracket allows me below to safely loop looking for specific character sets that don't match angle bracket // without also explicitly having to test for looping past the end of the string. if (xaml.Length < 2 || xaml[0] != '<' || xaml[xaml.Length - 1] != '>') { return XamlToRtfError.Unknown; } xamlIndex++; if (IsSpace(xaml[xamlIndex])) { return XamlToRtfError.Unknown; } // An end tag? if (xaml[xamlIndex] == '/') { return HandleEndTag(xaml, xamlIndex); } // Add the start and end of the tag pointers //AddParseData(xaml.Substring(xamlIndex)); int startIndex = xamlIndex; // Note that check above that the string ends in angle simplifies loop check for (xamlIndex++; IsNameChar(xaml[xamlIndex]); xamlIndex++) { continue; } AddParseData(xaml.Substring(startIndex, xamlIndex - startIndex)); // Start parsing name/value pairs while (xamlIndex < xaml.Length) { // Move past spaces for (; IsSpace(xaml[xamlIndex]); xamlIndex++) { continue; } // Done? if (xamlIndex == xaml.Length - 1) { break; } // Empty tag? if (xaml[xamlIndex] == '/') { if (xamlIndex == xaml.Length - 2) { _empty = true; break; } else { return XamlToRtfError.Unknown; } } // OK, have another attribute //AddParseData(xaml.Substring(xamlIndex)); startIndex = xamlIndex; for (xamlIndex++; IsNameChar(xaml[xamlIndex]); xamlIndex++) { continue; } AddParseData(xaml.Substring(startIndex, xamlIndex - startIndex)); // Move past optional trailing spaces if (xamlIndex < xaml.Length) { for (; IsSpace(xaml[xamlIndex]); xamlIndex++) { continue; } } // Attribute with no '='? if (xamlIndex == xaml.Length || xaml[xamlIndex] != '=') { return XamlToRtfError.Unknown; } // Move past '=' and optional trailing spaces xamlIndex++; for (; IsSpace(xaml[xamlIndex]); xamlIndex++) { continue; } // Value needs to be quoted if (xaml[xamlIndex] != '\'' && xaml[xamlIndex] != '"') { return XamlToRtfError.Unknown; } quoteChar = xaml[xamlIndex++]; //AddParseData(xaml.Substring(xamlIndex)); startIndex = xamlIndex; for (; xamlIndex < xaml.Length && xaml[xamlIndex] != quoteChar; xamlIndex++) { continue; } if (xamlIndex == xaml.Length) { return XamlToRtfError.Unknown; } AddParseData(xaml.Substring(startIndex, xamlIndex - startIndex)); xamlIndex++; } _valid = true; return xamlToRtfError; } internal void AddParseData(string parseData) { Add(parseData); } #endregion internal Methods // --------------------------------------------------------------------- // // internal Properties // // --------------------------------------------------------------------- #region internal Properties internal bool IsEmpty { get { return _empty; } } internal bool IsValid { get { return _valid; } } #endregion internal Properties #region Private Methods // ---------------------------------------------------------------------- // // Private Methods // // --------------------------------------------------------------------- private bool IsSpace(char character) { return (character == ' ' || character == '\t' || character == '\n' || character == '\r'); } private bool IsNameChar(char character) { return (!IsSpace(character) && character != '=' && character != '>' && character != '/'); } // Helper for Init method. private XamlToRtfError HandleEndTag(string xaml, int xamlIndex) { xamlIndex++; // Move past spaces for (; IsSpace(xaml[xamlIndex]); xamlIndex++) { continue; } // At name start int startIndex = xamlIndex; // Move past name for (xamlIndex++; IsNameChar(xaml[xamlIndex]); xamlIndex++) { continue; } AddParseData(xaml.Substring(startIndex, xamlIndex - startIndex)); // Move past spaces for (; IsSpace(xaml[xamlIndex]); xamlIndex++) { continue; } // Now must be at end of token if (xamlIndex == xaml.Length - 1) { _valid = true; return XamlToRtfError.None; } return XamlToRtfError.Unknown; } #endregion Private Methods // ---------------------------------------------------------------------- // // Private Fields // // ---------------------------------------------------------------------- #region Private Fields private bool _empty; private bool _valid; #endregion Private Fields } internal class XamlToken { //----------------------------------------------------- // // Constructors // //------------------------------------------------------ #region Constructors ////// /// internal XamlToken() { } #endregion Constructors // --------------------------------------------------------------------- // // internal Properties // // --------------------------------------------------------------------- #region internal Properties internal XamlTokenType TokenType { get { return _tokenType; } set { _tokenType = value; } } internal string Text { get { return _text; } set { _text = value; } } #endregion internal Properties // --------------------------------------------------------------------- // // Private Fields // // ---------------------------------------------------------------------- #region Private Fields private XamlTokenType _tokenType; private string _text; #endregion Private Fields } #endregion Private Class } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ChangesetResponse.cs
- BufferModeSettings.cs
- Helper.cs
- IPAddress.cs
- BitmapFrame.cs
- PartBasedPackageProperties.cs
- SplayTreeNode.cs
- SharedPersonalizationStateInfo.cs
- NamespaceEmitter.cs
- BitmapDownload.cs
- ThreadExceptionEvent.cs
- ContentPresenter.cs
- ModelPropertyCollectionImpl.cs
- Wildcard.cs
- StreamMarshaler.cs
- OleDbParameter.cs
- HyperLinkStyle.cs
- X509Chain.cs
- StrokeCollection2.cs
- TypeCollectionPropertyEditor.cs
- WpfXamlLoader.cs
- WsdlBuildProvider.cs
- TemplateAction.cs
- ManifestBasedResourceGroveler.cs
- CodeIdentifiers.cs
- ExternalCalls.cs
- RIPEMD160.cs
- ResourcePool.cs
- CodeBinaryOperatorExpression.cs
- Baml2006KeyRecord.cs
- TreeViewHitTestInfo.cs
- DataGridViewColumn.cs
- BinaryMethodMessage.cs
- SystemIPv6InterfaceProperties.cs
- ObjectListField.cs
- recordstatefactory.cs
- InsufficientMemoryException.cs
- QualifiedCellIdBoolean.cs
- SupportsEventValidationAttribute.cs
- FontConverter.cs
- CompilationSection.cs
- OraclePermissionAttribute.cs
- IdentityHolder.cs
- BamlResourceContent.cs
- WorkflowApplicationException.cs
- KeyboardNavigation.cs
- ProcessModelSection.cs
- DrawListViewItemEventArgs.cs
- ExpressionBuilderCollection.cs
- CultureSpecificStringDictionary.cs
- RootContext.cs
- CharacterMetrics.cs
- BufferBuilder.cs
- DBSchemaRow.cs
- DbCommandTree.cs
- TransformPatternIdentifiers.cs
- RecognizerInfo.cs
- ReadOnlyHierarchicalDataSourceView.cs
- GlyphRun.cs
- SmiRequestExecutor.cs
- UnconditionalPolicy.cs
- DocumentAutomationPeer.cs
- GlyphRunDrawing.cs
- PixelShader.cs
- ValidationResult.cs
- SkewTransform.cs
- QuestionEventArgs.cs
- UrlAuthFailedErrorFormatter.cs
- CompareValidator.cs
- CqlBlock.cs
- AncestorChangedEventArgs.cs
- PassportAuthenticationEventArgs.cs
- QueryAccessibilityHelpEvent.cs
- Win32Interop.cs
- SuppressMessageAttribute.cs
- SqlDataSourceRefreshSchemaForm.cs
- ContextStaticAttribute.cs
- RecognizeCompletedEventArgs.cs
- BinaryCommonClasses.cs
- TrackingProfileSerializer.cs
- TableAdapterManagerNameHandler.cs
- SplashScreenNativeMethods.cs
- RegexCapture.cs
- ConfigXmlSignificantWhitespace.cs
- DataGridViewRowHeaderCell.cs
- ImageClickEventArgs.cs
- COM2FontConverter.cs
- InstanceData.cs
- SqlBuffer.cs
- XmlSecureResolver.cs
- BindToObject.cs
- WizardPanelChangingEventArgs.cs
- SafeRightsManagementQueryHandle.cs
- ScaleTransform.cs
- ServiceAuthorizationManager.cs
- WindowsToolbarAsMenu.cs
- Char.cs
- SafeTokenHandle.cs
- AlternateView.cs
- FixedSOMContainer.cs