Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / MIT / System / Web / UI / MobileControls / LiteralTextParser.cs / 1305376 / LiteralTextParser.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Specialized; using System.Globalization; using System.Text; using System.Web; namespace System.Web.UI.MobileControls { /* * LiteralTextParser class. * * The LiteralTextParser class parses a string of literal text, * containing certain recognizable tags, and creates a set of controls * from them. Any unrecognized tags are ignored. * * This is an abstract base class. RuntimeLiteralTextParser and * CompileTimeLiteralTextParser inherit from this class. * * Copyright (c) 2000 Microsoft Corporation */ [Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")] internal abstract class LiteralTextParser { // The parsing methods (Parse, ParseTag, ParseTagAttributes, ParseText) // build up LiteralElement objects, which can either be text or tags. // ProcessElementInternal is then called. It combines some other data // and calls ProcessElement, a method which is overridable by inherited // classes. // Literal Element type - includes recognized tags. protected enum LiteralElementType { Unrecognized, Text, Bold, Italic, Break, Paragraph, Anchor, } // Available formatting options for literal elements. This enum can // be combined with the | operator. protected enum LiteralFormat { None = 0, Bold = 1, Italic = 2, } // Literal Element. protected class LiteralElement { public LiteralElementType Type; public IDictionary Attributes; public String Text; public LiteralFormat Format = LiteralFormat.None; public bool BreakAfter = false; public bool ForceBreakTag = false; public LiteralElement(String text) { Type = LiteralElementType.Text; Attributes = null; Text = text; } public LiteralElement(LiteralElementType type, IDictionary attributes) { Type = type; Attributes = attributes; Text = String.Empty; } public bool IsText { get { return Type == LiteralElementType.Text; } } public bool IsEmptyText { get { return IsText && !LiteralTextParser.IsValidText(Text); } } public String GetAttribute(String attributeName) { Object o = (Attributes != null) ? Attributes[attributeName] : null; return (o != null) ? (String)o : String.Empty; } } // Methods overriden by inherited classes. protected abstract void ProcessElement(LiteralElement element); protected abstract void ProcessTagInnerText(String text); private bool _isBreakingReset = true; private LiteralElement _lastQueuedElement = null; private LiteralElement _currentTag = null; private bool _beginNewParagraph = true; private FormatStack _formatStack = new FormatStack(); private bool _elementsProcessed = false; // Static constructor that builds a lookup table of recognized tags. private static IDictionary _recognizedTags = new Hashtable(); static LiteralTextParser() { // PERF: Add both lowercase and uppercase. _recognizedTags.Add("b", LiteralElementType.Bold); _recognizedTags.Add("B", LiteralElementType.Bold); _recognizedTags.Add("i", LiteralElementType.Italic); _recognizedTags.Add("I", LiteralElementType.Italic); _recognizedTags.Add("br", LiteralElementType.Break); _recognizedTags.Add("BR", LiteralElementType.Break); _recognizedTags.Add("p", LiteralElementType.Paragraph); _recognizedTags.Add("P", LiteralElementType.Paragraph); _recognizedTags.Add("a", LiteralElementType.Anchor); _recognizedTags.Add("A", LiteralElementType.Anchor); } // Convert a tag name to a type. private static LiteralElementType TagNameToType(String tagName) { Object o = _recognizedTags[tagName]; if (o == null) { o = _recognizedTags[tagName.ToLower(CultureInfo.InvariantCulture)]; } return (o != null) ? (LiteralElementType)o : LiteralElementType.Unrecognized; } // Returns true if any valid controls could be generated from the given text. internal /*public*/ static bool IsValidText(String validText) { // if (validText.Length == 0) { return false; } foreach (char c in validText) { if (!Char.IsWhiteSpace(c) && c != '\t' && c != '\r' && c != '\n') { return true; } } return false; } // Main parse routine. Called with a block of text to parse. internal /*public*/ void Parse(String literalText) { int length = literalText.Length; int currentPosition = 0; while (currentPosition < length) { // Find start of next tag. int nextTag = literalText.IndexOf('<', currentPosition); if (nextTag == -1) { ParseText(literalText.Substring(currentPosition)); break; } if (nextTag > currentPosition) { ParseText(literalText.Substring(currentPosition, nextTag - currentPosition)); } // Find end of tag. char quoteChar = '\0'; int endOfTag; for (endOfTag = nextTag + 1; endOfTag < length; endOfTag++) { char c = literalText[endOfTag]; if (quoteChar == '\0') { if (c == '\'' || c == '\"') { quoteChar = c; } else if (c == '>') { break; } } else { if (c == quoteChar) { quoteChar = '\0'; } } } if (endOfTag == length) { // break; } ParseTag(literalText, nextTag + 1, endOfTag); currentPosition = endOfTag + 1; } Flush(); } internal /*public*/ void ResetBreaking() { _isBreakingReset = true; ElementsProcessed = false; } internal /*public*/ void ResetNewParagraph() { _beginNewParagraph = false; } internal /*public*/ void UnResetBreaking() { _isBreakingReset = false; } protected bool ElementsProcessed { get { return _elementsProcessed; } set { _elementsProcessed = value; } } protected void OnAfterDataBoundLiteral() { ElementsProcessed = true; UnResetBreaking(); } // Parse a single tag. private void ParseTag(String literalText, int tagStart, int tagFinish) { bool isClosingTag = (literalText[tagStart] == '/'); if (isClosingTag) { tagStart++; } // Empty tag? if (tagStart == tagFinish) { return; } // Look for end of tag name. int tagNameFinish = tagStart; while (tagNameFinish < tagFinish && !Char.IsWhiteSpace(literalText[tagNameFinish]) && literalText[tagNameFinish] != '/') { tagNameFinish++; } // Extract tag name, and compare to recognized tags. String tagName = literalText.Substring(tagStart, tagNameFinish - tagStart); LiteralElementType tagType = TagNameToType(tagName); if (tagType == LiteralElementType.Unrecognized) { return; } // Are we already in a complex tag? if (_currentTag != null) { // Ignore any inner tags, except the closing tag. if (_currentTag.Type == tagType && isClosingTag) { ProcessElementInternal(_currentTag); _currentTag = null; } else { // } return; } switch (tagType) { case LiteralElementType.Paragraph: // Do not create two breaks forpairs. if (!_isBreakingReset) { _isBreakingReset = true; goto case LiteralElementType.Break; } break; case LiteralElementType.Break: // If a break is already pending, insert an empty one. if (_beginNewParagraph) { ParseText(String.Empty); } if (_lastQueuedElement != null && _lastQueuedElement.Text.Length == 0) { _lastQueuedElement.ForceBreakTag = true; } _beginNewParagraph = true; break; case LiteralElementType.Bold: if (isClosingTag) { _formatStack.Pop(FormatStack.Bold); } else { _formatStack.Push(FormatStack.Bold); } break; case LiteralElementType.Italic: if (isClosingTag) { _formatStack.Pop(FormatStack.Italic); } else { _formatStack.Push(FormatStack.Italic); } break; default: { if (!isClosingTag) { IDictionary attribs = ParseTagAttributes(literalText, tagNameFinish, tagFinish, tagName); _currentTag = new LiteralElement(tagType, attribs); } break; } } if (_isBreakingReset && tagType != LiteralElementType.Paragraph) { _isBreakingReset = false; } } protected bool IsInTag { get { return _currentTag != null; } } protected LiteralFormat CurrentFormat { get { return _formatStack.CurrentFormat; } } // Parse attributes of a tag. private enum AttributeParseState { StartingAttributeName, ReadingAttributeName, ReadingEqualSign, StartingAttributeValue, ReadingAttributeValue, Error, } private IDictionary ParseTagAttributes(String literalText, int attrStart, int attrFinish, String tagName) { if (attrFinish > attrStart && literalText[attrFinish - 1] == '/') { attrFinish--; } IDictionary dictionary = null; int attrPos = attrStart; bool skipWhiteSpaces = true; int attrNameStart = 0; int attrNameFinish = 0; int attrValueStart = 0; char quoteChar = '\0'; AttributeParseState state = AttributeParseState.StartingAttributeName; while (attrPos <= attrFinish && state != AttributeParseState.Error) { char c = attrPos == attrFinish ? '\0' : literalText[attrPos]; if (skipWhiteSpaces) { if (Char.IsWhiteSpace(c)) { attrPos++; continue; } else { skipWhiteSpaces = false; } } switch (state) { case AttributeParseState.StartingAttributeName: if (c == '\0') { attrPos = attrFinish + 1; } else { attrNameStart = attrPos; state = AttributeParseState.ReadingAttributeName; } break; case AttributeParseState.ReadingAttributeName: if (c == '=' || Char.IsWhiteSpace(c)) { attrNameFinish = attrPos; skipWhiteSpaces = true; state = AttributeParseState.ReadingEqualSign; } else if (c == '\0') { state = AttributeParseState.Error; } else { attrPos++; } break; case AttributeParseState.ReadingEqualSign: if (c == '=') { skipWhiteSpaces = true; state = AttributeParseState.StartingAttributeValue; attrPos++; } else { state = AttributeParseState.Error; } break; case AttributeParseState.StartingAttributeValue: attrValueStart = attrPos; if (c == '\0') { state = AttributeParseState.Error; break; } else if (c == '\"' || c == '\'') { quoteChar = c; attrValueStart++; attrPos++; } else { quoteChar = '\0'; } state = AttributeParseState.ReadingAttributeValue; break; case AttributeParseState.ReadingAttributeValue: if (c == quoteChar || ((Char.IsWhiteSpace(c) || c == '\0') && quoteChar == '\0')) { if (attrNameFinish == attrNameStart) { state = AttributeParseState.Error; break; } if (dictionary == null) { dictionary = new HybridDictionary(true); } dictionary.Add( literalText.Substring(attrNameStart, attrNameFinish - attrNameStart), literalText.Substring(attrValueStart, attrPos - attrValueStart)); skipWhiteSpaces = true; state = AttributeParseState.StartingAttributeName; if (c == quoteChar) { attrPos++; } } else { attrPos++; } break; } } if (state == AttributeParseState.Error) { throw new Exception(SR.GetString(SR.LiteralTextParser_InvalidTagFormat)); } return dictionary; } // Parse a plain text literal. private void ParseText(String text) { if (_currentTag != null) { // Add to inner text of tag. _currentTag.Text += text; } else { if (_isBreakingReset && IsValidText(text)) { _isBreakingReset = false; } ProcessElementInternal(new LiteralElement(text)); } } private void ProcessElementInternal(LiteralElement element) { // This method needs to fill in an element with formatting and // breaking information, and calls ProcessElement. However, // each element needs to know whether there will be a break // AFTER the element, so elements are processed lazily, keeping // the last one in a single-element queue. LiteralFormat currentFormat = _formatStack.CurrentFormat; if (_lastQueuedElement != null) { // If both the last and current element are text elements, and // the formatting hasn't changed, then just combine the two into // a single element. if (_lastQueuedElement.IsText && element.IsText && (_lastQueuedElement.Format == currentFormat) && !_beginNewParagraph) { _lastQueuedElement.Text += element.Text; return; } else if (_lastQueuedElement.IsEmptyText && !_beginNewParagraph && IgnoreWhiteSpaceElement(_lastQueuedElement)) { // Empty text element with no breaks - so just ignore. } else { _lastQueuedElement.BreakAfter = _beginNewParagraph; ProcessElement(_lastQueuedElement); ElementsProcessed = true; } } _lastQueuedElement = element; _lastQueuedElement.Format = currentFormat; _beginNewParagraph = false; } private void Flush() { if (_currentTag != null) { // In the middle of a tag. There may be multiple inner text elements inside // a tag, e.g. // some text <%# a databinding %> some more text // and we're being flushed just at the start of the databinding. if (!_currentTag.IsEmptyText) { ProcessTagInnerText(_currentTag.Text); } _currentTag.Text = String.Empty; return; } if (_lastQueuedElement == null) { return; } // Ignore orphaned whitespace. if (!_lastQueuedElement.ForceBreakTag && _lastQueuedElement.IsEmptyText) { if (!ElementsProcessed) { return; } if (_lastQueuedElement.Text.Length == 0 || _lastQueuedElement.Text[0] != ' ') { return; } _lastQueuedElement.Text = " "; } _lastQueuedElement.BreakAfter = _beginNewParagraph; ProcessElement(_lastQueuedElement); _lastQueuedElement = null; } protected virtual bool IgnoreWhiteSpaceElement(LiteralElement element) { return true; } /* * FormatStack private class * * This class maintains a simple stack of formatting directives. As tags and * closing tags are processed, they are pushed on and popped off this stack. * The CurrentFormat property returns the current state. */ private class FormatStack { internal const char Bold = 'b'; internal const char Italic = 'i'; private StringBuilder _stringBuilder = new StringBuilder(16); public void Push(char option) { _stringBuilder.Append(option); } public void Pop(char option) { // Only pop a matching directive - non-matching directives are ignored! int length = _stringBuilder.Length; if (length > 0 && _stringBuilder[length - 1] == option) { _stringBuilder.Remove(length - 1, 1); } } public LiteralFormat CurrentFormat { get { LiteralFormat format = LiteralFormat.None; for (int i = _stringBuilder.Length - 1; i >= 0; i--) { switch (_stringBuilder[i]) { case Bold: format |= LiteralFormat.Bold; break; case Italic: format |= LiteralFormat.Italic; break; } } return format; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DynamicDataRouteHandler.cs
- CodeAttributeDeclarationCollection.cs
- ToolBar.cs
- SecurityRuntime.cs
- TemplateContent.cs
- SiteMapNodeItemEventArgs.cs
- MimeTypeMapper.cs
- XmlSerializationReader.cs
- XmlWhitespace.cs
- NegotiateStream.cs
- ContentPlaceHolder.cs
- SafeViewOfFileHandle.cs
- PropertyPath.cs
- StateInitialization.cs
- NonceToken.cs
- RSAOAEPKeyExchangeDeformatter.cs
- XmlSchemaSubstitutionGroup.cs
- EncodingInfo.cs
- WindowsFormsDesignerOptionService.cs
- SafeNativeMethods.cs
- TrustLevel.cs
- HttpsTransportBindingElement.cs
- StylusPointPropertyUnit.cs
- dataprotectionpermissionattribute.cs
- SqlUtil.cs
- RsaKeyIdentifierClause.cs
- StreamHelper.cs
- ReflectionUtil.cs
- ToolStripItemTextRenderEventArgs.cs
- MemberJoinTreeNode.cs
- StrongNameMembershipCondition.cs
- ServiceObjectContainer.cs
- EntityWithChangeTrackerStrategy.cs
- EmbeddedMailObjectsCollection.cs
- MonitoringDescriptionAttribute.cs
- HebrewNumber.cs
- XPathBuilder.cs
- DependentList.cs
- ExpressionConverter.cs
- SpotLight.cs
- XmlSchemaSimpleTypeRestriction.cs
- SR.cs
- Validator.cs
- CryptoApi.cs
- XmlSignatureManifest.cs
- PriorityRange.cs
- RoutedUICommand.cs
- FamilyMap.cs
- AmbientLight.cs
- DataListAutoFormat.cs
- AccessorTable.cs
- SecureStringHasher.cs
- Random.cs
- FixedPosition.cs
- Base64Stream.cs
- MDIClient.cs
- SpecialFolderEnumConverter.cs
- _HeaderInfo.cs
- TransformGroup.cs
- BlobPersonalizationState.cs
- Helpers.cs
- BufferedWebEventProvider.cs
- StrongNameMembershipCondition.cs
- EntityFunctions.cs
- RectangleGeometry.cs
- UnknownWrapper.cs
- HttpListenerPrefixCollection.cs
- UpWmlMobileTextWriter.cs
- ReverseComparer.cs
- DocumentPageHost.cs
- HtmlLinkAdapter.cs
- SubtreeProcessor.cs
- RunWorkerCompletedEventArgs.cs
- BoolExpressionVisitors.cs
- CacheMode.cs
- DirectoryObjectSecurity.cs
- DataBindingsDialog.cs
- BoolExpression.cs
- QueryOutputWriter.cs
- ConstructorBuilder.cs
- EFTableProvider.cs
- OLEDB_Util.cs
- TypeRestriction.cs
- Expression.cs
- FaultReasonText.cs
- DesignerFrame.cs
- WindowsFormsHost.cs
- DescendantQuery.cs
- OdbcException.cs
- SqlPersonalizationProvider.cs
- PermissionSetEnumerator.cs
- SQLDecimal.cs
- SystemTcpStatistics.cs
- TouchEventArgs.cs
- FormParameter.cs
- HttpDebugHandler.cs
- FragmentNavigationEventArgs.cs
- XmlIncludeAttribute.cs
- WindowsSlider.cs
- NullableFloatMinMaxAggregationOperator.cs