Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / XmlUtils / System / Xml / Xsl / Runtime / XmlAttributeCache.cs / 1305376 / XmlAttributeCache.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace System.Xml.Xsl.Runtime { using System; using System.Diagnostics; using System.Xml; using System.Xml.XPath; using System.Xml.Schema; ////// This writer supports only writer methods which write attributes. Attributes are stored in a /// data structure until StartElementContent() is called, at which time the attributes are flushed /// to the wrapped writer. In the case of duplicate attributes, the last attribute's value is used. /// internal sealed class XmlAttributeCache : XmlRawWriter, IRemovableWriter { private XmlRawWriter wrapped; private OnRemoveWriter onRemove; // Event handler that is called when cached attributes are flushed to wrapped writer private AttrNameVal[] arrAttrs; // List of cached attribute names and value parts private int numEntries; // Number of attributes in the cache private int idxLastName; // The entry containing the name of the last attribute to be cached private int hashCodeUnion; // Set of hash bits that can quickly guarantee a name is not a duplicate ////// Initialize the cache. Use this method instead of a constructor in order to reuse the cache. /// public void Init(XmlRawWriter wrapped) { SetWrappedWriter(wrapped); // Clear attribute list this.numEntries = 0; this.idxLastName = 0; this.hashCodeUnion = 0; } ////// Return the number of cached attributes. /// public int Count { get { return this.numEntries; } } //----------------------------------------------- // IRemovableWriter interface //----------------------------------------------- ////// This writer will raise this event once cached attributes have been flushed in order to signal that the cache /// no longer needs to be part of the pipeline. /// public OnRemoveWriter OnRemoveWriterEvent { get { return this.onRemove; } set { this.onRemove = value; } } ////// The wrapped writer will callback on this method if it wishes to remove itself from the pipeline. /// private void SetWrappedWriter(XmlRawWriter writer) { // If new writer might remove itself from pipeline, have it callback on this method when its ready to go IRemovableWriter removable = writer as IRemovableWriter; if (removable != null) removable.OnRemoveWriterEvent = SetWrappedWriter; this.wrapped = writer; } //----------------------------------------------- // XmlWriter interface //----------------------------------------------- ////// Add an attribute to the cache. If an attribute if the same name already exists, replace it. /// public override void WriteStartAttribute(string prefix, string localName, string ns) { int hashCode; int idx = 0; Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null); // Compute hashcode based on first letter of the localName hashCode = (1 << ((int) localName[0] & 31)); // If the hashcode is not in the union, then name will not be found by a scan if ((this.hashCodeUnion & hashCode) != 0) { // The name may or may not be present, so scan for it Debug.Assert(this.numEntries != 0); do { if (this.arrAttrs[idx].IsDuplicate(localName, ns, hashCode)) break; // Next attribute name idx = this.arrAttrs[idx].NextNameIndex; } while (idx != 0); } else { // Insert hashcode into union this.hashCodeUnion |= hashCode; } // Insert new attribute; link attribute names together in a list EnsureAttributeCache(); if (this.numEntries != 0) this.arrAttrs[this.idxLastName].NextNameIndex = this.numEntries; this.idxLastName = this.numEntries++; this.arrAttrs[this.idxLastName].Init(prefix, localName, ns, hashCode); } ////// No-op. /// public override void WriteEndAttribute() { } ////// Pass through namespaces to underlying writer. If any attributes have been cached, flush them. /// internal override void WriteNamespaceDeclaration(string prefix, string ns) { FlushAttributes(); this.wrapped.WriteNamespaceDeclaration(prefix, ns); } ////// Add a block of text to the cache. This text block makes up some or all of the untyped string /// value of the current attribute. /// public override void WriteString(string text) { Debug.Assert(text != null); Debug.Assert(this.arrAttrs != null && this.numEntries != 0); EnsureAttributeCache(); this.arrAttrs[this.numEntries++].Init(text); } ////// All other WriteValue methods are implemented by XmlWriter to delegate to WriteValue(object) or WriteValue(string), so /// only these two methods need to be implemented. /// public override void WriteValue(object value) { Debug.Assert(value is XmlAtomicValue, "value should always be an XmlAtomicValue, as XmlAttributeCache is only used by XmlQueryOutput"); Debug.Assert(this.arrAttrs != null && this.numEntries != 0); EnsureAttributeCache(); this.arrAttrs[this.numEntries++].Init((XmlAtomicValue) value); } public override void WriteValue(string value) { WriteValue(value); } ////// Send cached, non-overriden attributes to the specified writer. Calling this method has /// the side effect of clearing the attribute cache. /// internal override void StartElementContent() { FlushAttributes(); // Call StartElementContent on wrapped writer this.wrapped.StartElementContent(); } public override void WriteStartElement(string prefix, string localName, string ns) { Debug.Assert(false, "Should never be called on XmlAttributeCache."); } internal override void WriteEndElement(string prefix, string localName, string ns) { Debug.Assert(false, "Should never be called on XmlAttributeCache."); } public override void WriteComment(string text) { Debug.Assert(false, "Should never be called on XmlAttributeCache."); } public override void WriteProcessingInstruction(string name, string text) { Debug.Assert(false, "Should never be called on XmlAttributeCache."); } public override void WriteEntityRef(string name) { Debug.Assert(false, "Should never be called on XmlAttributeCache."); } ////// Forward call to wrapped writer. /// public override void Close() { this.wrapped.Close(); } ////// Forward call to wrapped writer. /// public override void Flush() { this.wrapped.Flush(); } //----------------------------------------------- // Helper methods //----------------------------------------------- private void FlushAttributes() { int idx = 0, idxNext; string localName; while (idx != this.numEntries) { // Get index of next attribute's name (0 if this is the last attribute) idxNext = this.arrAttrs[idx].NextNameIndex; if (idxNext == 0) idxNext = this.numEntries; // If localName is null, then this is a duplicate attribute that has been marked as "deleted" localName = this.arrAttrs[idx].LocalName; if (localName != null) { string prefix = this.arrAttrs[idx].Prefix; string ns = this.arrAttrs[idx].Namespace; this.wrapped.WriteStartAttribute(prefix, localName, ns); // Output all of this attribute's text or typed values while (++idx != idxNext) { string text = this.arrAttrs[idx].Text; if (text != null) this.wrapped.WriteString(text); else this.wrapped.WriteValue(this.arrAttrs[idx].Value); } this.wrapped.WriteEndAttribute(); } else { // Skip over duplicate attributes idx = idxNext; } } // Notify event listener that attributes have been flushed if (this.onRemove != null) this.onRemove(this.wrapped); } private struct AttrNameVal { private string localName; private string prefix; private string namespaceName; private string text; private XmlAtomicValue value; private int hashCode; private int nextNameIndex; public string LocalName { get { return this.localName; } } public string Prefix { get { return this.prefix; } } public string Namespace { get { return this.namespaceName; } } public string Text { get { return this.text; } } public XmlAtomicValue Value { get { return this.value; } } public int NextNameIndex { get { return this.nextNameIndex; } set { this.nextNameIndex = value; } } ////// Cache an attribute's name and type. /// public void Init(string prefix, string localName, string ns, int hashCode) { this.localName = localName; this.prefix = prefix; this.namespaceName = ns; this.hashCode = hashCode; this.nextNameIndex = 0; } ////// Cache all or part of the attribute's string value. /// public void Init(string text) { this.text = text; this.value = null; } ////// Cache all or part of the attribute's typed value. /// public void Init(XmlAtomicValue value) { this.text = null; this.value = value; } ////// Returns true if this attribute has the specified name (and thus is a duplicate). /// public bool IsDuplicate(string localName, string ns, int hashCode) { // If attribute is not marked as deleted if (this.localName != null) { // And if hash codes match, if (this.hashCode == hashCode) { // And if local names match, if (this.localName.Equals(localName)) { // And if namespaces match, if (this.namespaceName.Equals(ns)) { // Then found duplicate attribute, so mark the attribute as deleted this.localName = null; return true; } } } } return false; } } #if DEBUG private const int DefaultCacheSize = 2; #else private const int DefaultCacheSize = 32; #endif ////// Ensure that attribute array has been created and is large enough for at least one /// additional entry. /// private void EnsureAttributeCache() { if (this.arrAttrs == null) { // Create caching array this.arrAttrs = new AttrNameVal[DefaultCacheSize]; } else if (this.numEntries >= this.arrAttrs.Length) { // Resize caching array Debug.Assert(this.numEntries == this.arrAttrs.Length); AttrNameVal[] arrNew = new AttrNameVal[this.numEntries * 2]; Array.Copy(this.arrAttrs, arrNew, this.numEntries); this.arrAttrs = arrNew; } } } } // 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
- CriticalFinalizerObject.cs
- MsmqBindingElementBase.cs
- EffectiveValueEntry.cs
- GridViewCellAutomationPeer.cs
- Int16KeyFrameCollection.cs
- AssemblyResourceLoader.cs
- FlagsAttribute.cs
- ResourceReferenceExpression.cs
- AdornerHitTestResult.cs
- ParenExpr.cs
- ListViewItem.cs
- CodeCommentStatementCollection.cs
- ObjectSet.cs
- DbConnectionPoolIdentity.cs
- SessionPageStateSection.cs
- CheckBox.cs
- PostBackOptions.cs
- Message.cs
- TransferMode.cs
- Vector3DConverter.cs
- ToolboxItemWrapper.cs
- InternalTypeHelper.cs
- HostProtectionPermission.cs
- User.cs
- DesignTimeParseData.cs
- ScaleTransform.cs
- RelatedCurrencyManager.cs
- Privilege.cs
- SrgsSemanticInterpretationTag.cs
- InfoCardArgumentException.cs
- ScalarOps.cs
- DataGridViewImageCell.cs
- CodeFieldReferenceExpression.cs
- CursorConverter.cs
- ColorAnimationBase.cs
- activationcontext.cs
- MailBnfHelper.cs
- BoundColumn.cs
- ButtonBaseAdapter.cs
- ServiceProviders.cs
- SqlClientPermission.cs
- SizeConverter.cs
- ListViewSortEventArgs.cs
- TypeGeneratedEventArgs.cs
- WebMessageEncodingElement.cs
- DesignerForm.cs
- ManagedFilter.cs
- DefaultValueTypeConverter.cs
- ComponentCommands.cs
- SqlMultiplexer.cs
- SupportedAddressingMode.cs
- DrawListViewColumnHeaderEventArgs.cs
- AutoGeneratedFieldProperties.cs
- newitemfactory.cs
- Stack.cs
- RMPublishingDialog.cs
- CodeCompiler.cs
- FlowLayoutPanel.cs
- JournalEntry.cs
- Membership.cs
- OutputWindow.cs
- FontNamesConverter.cs
- WebPartConnection.cs
- ContentTextAutomationPeer.cs
- ObjectTag.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- XPathNodeInfoAtom.cs
- Int16Converter.cs
- Cloud.cs
- MemoryFailPoint.cs
- ConvertEvent.cs
- ManagedFilter.cs
- SBCSCodePageEncoding.cs
- AutomationAttributeInfo.cs
- SplashScreenNativeMethods.cs
- LoginCancelEventArgs.cs
- CodeConditionStatement.cs
- XmlSchemaDatatype.cs
- TrueReadOnlyCollection.cs
- SortableBindingList.cs
- DoubleAnimation.cs
- BitmapEffect.cs
- InheritablePropertyChangeInfo.cs
- DateTimeValueSerializer.cs
- HttpDebugHandler.cs
- MimeBasePart.cs
- CriticalExceptions.cs
- QilList.cs
- ImageMapEventArgs.cs
- ButtonFieldBase.cs
- HierarchicalDataSourceControl.cs
- HtmlInputHidden.cs
- UserPersonalizationStateInfo.cs
- DataGridViewTextBoxColumn.cs
- TraceUtility.cs
- TCPClient.cs
- StringDictionary.cs
- TreeNodeCollection.cs
- ClientSession.cs
- InitializationEventAttribute.cs