Code:
/ 4.0 / 4.0 / 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. //------------------------------------------------------------------------------ //// 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
- TdsParserSessionPool.cs
- XmlAttributeOverrides.cs
- SelectionWordBreaker.cs
- CodeMemberField.cs
- XmlWriterDelegator.cs
- Rect3DValueSerializer.cs
- ObjectDataSourceChooseMethodsPanel.cs
- WorkflowQueueInfo.cs
- LocalizabilityAttribute.cs
- TreeViewImageKeyConverter.cs
- ListBase.cs
- Literal.cs
- StateBag.cs
- FacetValues.cs
- InProcStateClientManager.cs
- InputProcessorProfilesLoader.cs
- Win32KeyboardDevice.cs
- ParseHttpDate.cs
- UIElementPropertyUndoUnit.cs
- ArglessEventHandlerProxy.cs
- SessionEndingCancelEventArgs.cs
- ObjectListCommandCollection.cs
- ServiceProviders.cs
- Soap12ServerProtocol.cs
- Repeater.cs
- InitiatorSessionSymmetricMessageSecurityProtocol.cs
- ConstraintStruct.cs
- DecoderBestFitFallback.cs
- ClientConvert.cs
- MachineKey.cs
- SystemThemeKey.cs
- UdpMessageProperty.cs
- TransformedBitmap.cs
- HtmlControlPersistable.cs
- StateRuntime.cs
- LicenseException.cs
- RichTextBoxAutomationPeer.cs
- HandleRef.cs
- TextBoxView.cs
- ConstraintEnumerator.cs
- InsufficientMemoryException.cs
- COSERVERINFO.cs
- EntityViewGenerationConstants.cs
- CodeDomSerializer.cs
- ConditionedDesigner.cs
- HyperLinkColumn.cs
- ScriptingWebServicesSectionGroup.cs
- EqualityComparer.cs
- WindowsFormsHelpers.cs
- PageAsyncTaskManager.cs
- BooleanToVisibilityConverter.cs
- ProfileManager.cs
- MessageDecoder.cs
- Int64AnimationUsingKeyFrames.cs
- RenderDataDrawingContext.cs
- SimpleBitVector32.cs
- Freezable.cs
- PerfCounterSection.cs
- HwndSourceParameters.cs
- WsdlServiceChannelBuilder.cs
- DefinitionBase.cs
- ApplicationException.cs
- IntegerValidatorAttribute.cs
- IsolationInterop.cs
- RepeatBehaviorConverter.cs
- SqlResolver.cs
- ClosableStream.cs
- ChtmlCommandAdapter.cs
- DataObject.cs
- WorkflowItemsPresenter.cs
- CommentAction.cs
- ToolboxItemSnapLineBehavior.cs
- EventLogPermissionAttribute.cs
- manifestimages.cs
- ValueOfAction.cs
- SmtpSection.cs
- RuleSettings.cs
- Context.cs
- AsyncCompletedEventArgs.cs
- EntityUtil.cs
- EdmSchemaAttribute.cs
- Reference.cs
- ArgIterator.cs
- InteropTrackingRecord.cs
- QuotedPrintableStream.cs
- DrawListViewItemEventArgs.cs
- RtType.cs
- DataRow.cs
- AQNBuilder.cs
- Int64AnimationUsingKeyFrames.cs
- ImmutablePropertyDescriptorGridEntry.cs
- Win32KeyboardDevice.cs
- BookmarkUndoUnit.cs
- LoadedOrUnloadedOperation.cs
- ActivityTypeResolver.xaml.cs
- MenuItem.cs
- RtfToXamlReader.cs
- FontWeights.cs
- MergeFilterQuery.cs
- CurrencyManager.cs