XmlWellformedWriterHelpers.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Xml / System / Xml / Core / XmlWellformedWriterHelpers.cs / 1305376 / XmlWellformedWriterHelpers.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
using System; 
using System.Text;
using System.Diagnostics; 
using System.Collections.Generic;

namespace System.Xml {
 
    internal partial class XmlWellFormedWriter : XmlWriter {
        // 
        // Private types 
        //
        class NamespaceResolverProxy : IXmlNamespaceResolver { 
            XmlWellFormedWriter wfWriter;

            internal NamespaceResolverProxy(XmlWellFormedWriter wfWriter) {
                this.wfWriter = wfWriter; 
            }
 
            IDictionary IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope) { 
                throw new NotImplementedException();
            } 
            string IXmlNamespaceResolver.LookupNamespace(string prefix) {
                return wfWriter.LookupNamespace(prefix);
            }
 
            string IXmlNamespaceResolver.LookupPrefix(string namespaceName) {
                return wfWriter.LookupPrefix(namespaceName); 
            } 
        }
 
        struct ElementScope {
            internal int prevNSTop;
            internal string prefix;
            internal string localName; 
            internal string namespaceUri;
            internal XmlSpace xmlSpace; 
            internal string xmlLang; 

            internal void Set(string prefix, string localName, string namespaceUri, int prevNSTop) { 
                this.prevNSTop = prevNSTop;
                this.prefix = prefix;
                this.namespaceUri = namespaceUri;
                this.localName = localName; 
                this.xmlSpace = (System.Xml.XmlSpace)(int)-1;
                this.xmlLang = null; 
            } 

            internal void WriteEndElement(XmlRawWriter rawWriter) { 
                rawWriter.WriteEndElement(prefix, localName, namespaceUri);
            }

            internal void WriteFullEndElement(XmlRawWriter rawWriter) { 
                rawWriter.WriteFullEndElement(prefix, localName, namespaceUri);
            } 
        } 

        enum NamespaceKind { 
            Written,
            NeedToWrite,
            Implied,
            Special, 
        }
 
        struct Namespace { 
            internal string prefix;
            internal string namespaceUri; 
            internal NamespaceKind kind;
            internal int prevNsIndex;

            internal void Set(string prefix, string namespaceUri, NamespaceKind kind) { 
                this.prefix = prefix;
                this.namespaceUri = namespaceUri; 
                this.kind = kind; 
                this.prevNsIndex = -1;
            } 

            internal void WriteDecl(XmlWriter writer, XmlRawWriter rawWriter) {
                Debug.Assert(kind == NamespaceKind.NeedToWrite);
                if (null != rawWriter) { 
                    rawWriter.WriteNamespaceDeclaration(prefix, namespaceUri);
                } 
                else { 
                    if (prefix.Length == 0) {
                        writer.WriteStartAttribute(string.Empty, "xmlns", XmlReservedNs.NsXmlNs); 
                    }
                    else {
                        writer.WriteStartAttribute("xmlns", prefix, XmlReservedNs.NsXmlNs);
                    } 
                    writer.WriteString(namespaceUri);
                    writer.WriteEndAttribute(); 
                } 
            }
        } 

        struct AttrName {
            internal string prefix;
            internal string namespaceUri; 
            internal string localName;
            internal int prev; 
 
            internal void Set(string prefix, string localName, string namespaceUri) {
                this.prefix = prefix; 
                this.namespaceUri = namespaceUri;
                this.localName = localName;
                this.prev = 0;
            } 

            internal bool IsDuplicate(string prefix, string localName, string namespaceUri) { 
                return ((this.localName == localName) 
                    && ((this.prefix == prefix) || (this.namespaceUri == namespaceUri)));
            } 
        }

        enum SpecialAttribute {
            No = 0, 
            DefaultXmlns,
            PrefixedXmlns, 
            XmlSpace, 
            XmlLang
        } 

        class AttributeValueCache {
            enum ItemType {
                EntityRef, 
                CharEntity,
                SurrogateCharEntity, 
                Whitespace, 
                String,
                StringChars, 
                Raw,
                RawChars,
                ValueString,
            } 

            class Item { 
                internal ItemType type; 
                internal object data;
 
                internal Item() { }

                internal void Set(ItemType type, object data) {
                    this.type = type; 
                    this.data = data;
                } 
            } 

            class BufferChunk { 
                internal char[] buffer;
                internal int index;
                internal int count;
 
                internal BufferChunk(char[] buffer, int index, int count) {
                    this.buffer = buffer; 
                    this.index = index; 
                    this.count = count;
                } 
            }

            StringBuilder stringValue = new StringBuilder();
            string singleStringValue; // special-case for a single WriteString call 
            Item[] items;
            int firstItem; 
            int lastItem = -1; 

            internal string StringValue { 
                get {
                    if (singleStringValue != null) {
                        return singleStringValue;
                    } 
                    else {
                        return stringValue.ToString(); 
                    } 
                }
            } 

            internal void WriteEntityRef(string name) {
                if (singleStringValue != null) {
                    StartComplexValue(); 
                }
 
                switch (name) { 
                    case "lt":
                        stringValue.Append('<'); 
                        break;
                    case "gt":
                        stringValue.Append('>');
                        break; 
                    case "quot":
                        stringValue.Append('"'); 
                        break; 
                    case "apos":
                        stringValue.Append('\''); 
                        break;
                    case "amp":
                        stringValue.Append('&');
                        break; 
                    default:
                        stringValue.Append('&'); 
                        stringValue.Append(name); 
                        stringValue.Append(';');
                        break; 
                }

                AddItem(ItemType.EntityRef, name);
            } 

            internal void WriteCharEntity(char ch) { 
                if (singleStringValue != null) { 
                    StartComplexValue();
                } 
                stringValue.Append(ch);
                AddItem(ItemType.CharEntity, ch);
            }
 
            internal void WriteSurrogateCharEntity(char lowChar, char highChar) {
                if (singleStringValue != null) { 
                    StartComplexValue(); 
                }
                stringValue.Append(highChar); 
                stringValue.Append(lowChar);
                AddItem(ItemType.SurrogateCharEntity, new char[] { lowChar, highChar });
            }
 
            internal void WriteWhitespace(string ws) {
                if (singleStringValue != null) { 
                    StartComplexValue(); 
                }
                stringValue.Append(ws); 
                AddItem(ItemType.Whitespace, ws);
            }

            internal void WriteString(string text) { 
                if (singleStringValue != null) {
                    StartComplexValue(); 
                } 
                else {
                    // special-case for a single WriteString 
                    if (lastItem == -1) {
                        singleStringValue = text;
                        return;
                    } 
                }
 
                stringValue.Append(text); 
                AddItem(ItemType.String, text);
            } 

            internal void WriteChars(char[] buffer, int index, int count) {
                if (singleStringValue != null) {
                    StartComplexValue(); 
                }
                stringValue.Append(buffer, index, count); 
                AddItem(ItemType.StringChars, new BufferChunk(buffer, index, count)); 
            }
 
            internal void WriteRaw(char[] buffer, int index, int count) {
                if (singleStringValue != null) {
                    StartComplexValue();
                } 
                stringValue.Append(buffer, index, count);
                AddItem(ItemType.RawChars, new BufferChunk(buffer, index, count)); 
            } 

            internal void WriteRaw(string data) { 
                if (singleStringValue != null) {
                    StartComplexValue();
                }
                stringValue.Append(data); 
                AddItem(ItemType.Raw, data);
            } 
 
            internal void WriteValue(string value) {
                if (singleStringValue != null) { 
                    StartComplexValue();
                }
                stringValue.Append(value);
                AddItem(ItemType.ValueString, value); 
            }
 
            internal void Replay(XmlWriter writer) { 
                if (singleStringValue != null) {
                    writer.WriteString(singleStringValue); 
                    return;
                }

                BufferChunk bufChunk; 
                for (int i = firstItem; i <= lastItem; i++) {
                    Item item = items[i]; 
                    switch (item.type) { 
                        case ItemType.EntityRef:
                            writer.WriteEntityRef((string)item.data); 
                            break;
                        case ItemType.CharEntity:
                            writer.WriteCharEntity((char)item.data);
                            break; 
                        case ItemType.SurrogateCharEntity:
                            char[] chars = (char[])item.data; 
                            writer.WriteSurrogateCharEntity(chars[0], chars[1]); 
                            break;
                        case ItemType.Whitespace: 
                            writer.WriteWhitespace((string)item.data);
                            break;
                        case ItemType.String:
                            writer.WriteString((string)item.data); 
                            break;
                        case ItemType.StringChars: 
                            bufChunk = (BufferChunk)item.data; 
                            writer.WriteChars(bufChunk.buffer, bufChunk.index, bufChunk.count);
                            break; 
                        case ItemType.Raw:
                            writer.WriteRaw((string)item.data);
                            break;
                        case ItemType.RawChars: 
                            bufChunk = (BufferChunk)item.data;
                            writer.WriteChars(bufChunk.buffer, bufChunk.index, bufChunk.count); 
                            break; 
                        case ItemType.ValueString:
                            writer.WriteValue((string)item.data); 
                            break;
                        default:
                            Debug.Assert(false, "Unexpected ItemType value.");
                            break; 
                    }
                } 
            } 

            // This method trims whitespaces from the beginnig and the end of the string and cached writer events 
            internal void Trim() {
                // if only one string value -> trim the write spaces directly
                if (singleStringValue != null) {
                    singleStringValue = XmlConvert.TrimString(singleStringValue); 
                    return;
                } 
 
                // trim the string in StringBuilder
                string valBefore = stringValue.ToString(); 
                string valAfter = XmlConvert.TrimString(valBefore);
                if (valBefore != valAfter) {
                    stringValue = new StringBuilder(valAfter);
                } 

                // trim the beginning of the recorded writer events 
                XmlCharType xmlCharType = XmlCharType.Instance; 

                int i = firstItem; 
                while (i == firstItem && i <= lastItem) {
                    Item item = items[i];
                    switch (item.type) {
                        case ItemType.Whitespace: 
                            firstItem++;
                            break; 
                        case ItemType.String: 
                        case ItemType.Raw:
                        case ItemType.ValueString: 
                            item.data = XmlConvert.TrimStringStart((string)item.data);
                            if (((string)item.data).Length == 0) {
                                // no characters left -> move the firstItem index to exclude it from the Replay
                                firstItem++; 
                            }
                            break; 
                        case ItemType.StringChars: 
                        case ItemType.RawChars:
                            BufferChunk bufChunk = (BufferChunk)item.data; 
                            int endIndex = bufChunk.index + bufChunk.count;
                            while (bufChunk.index < endIndex && xmlCharType.IsWhiteSpace(bufChunk.buffer[bufChunk.index])) {
                                bufChunk.index++;
                                bufChunk.count--; 
                            }
                            if (bufChunk.index == endIndex) { 
                                // no characters left -> move the firstItem index to exclude it from the Replay 
                                firstItem++;
                            } 
                            break;
                    }
                    i++;
                } 

                // trim the end of the recorded writer events 
                i = lastItem; 
                while (i == lastItem && i >= firstItem) {
                    Item item = items[i]; 
                    switch (item.type) {
                        case ItemType.Whitespace:
                            lastItem--;
                            break; 
                        case ItemType.String:
                        case ItemType.Raw: 
                        case ItemType.ValueString: 
                            item.data = XmlConvert.TrimStringEnd((string)item.data);
                            if (((string)item.data).Length == 0) { 
                                // no characters left -> move the lastItem index to exclude it from the Replay
                                lastItem--;
                            }
                            break; 
                        case ItemType.StringChars:
                        case ItemType.RawChars: 
                            BufferChunk bufChunk = (BufferChunk)item.data; 
                            while (bufChunk.count > 0 && xmlCharType.IsWhiteSpace(bufChunk.buffer[bufChunk.index + bufChunk.count - 1])) {
                                bufChunk.count--; 
                            }
                            if (bufChunk.count == 0) {
                                // no characters left -> move the lastItem index to exclude it from the Replay
                                lastItem--; 
                            }
                            break; 
                    } 
                    i--;
                } 
            }

            internal void Clear() {
                singleStringValue = null; 
                lastItem = -1;
                firstItem = 0; 
                stringValue.Length = 0; 
            }
 
            private void StartComplexValue() {
                Debug.Assert(singleStringValue != null);
                Debug.Assert(lastItem == -1);
 
                stringValue.Append( singleStringValue );
                AddItem(ItemType.String, singleStringValue); 
 
                singleStringValue = null;
            } 

            void AddItem(ItemType type, object data) {
                int newItemIndex = lastItem + 1;
                if (items == null) { 
                    items = new Item[4];
                } 
                else if (items.Length == newItemIndex) { 
                    Item[] newItems = new Item[newItemIndex * 2];
                    Array.Copy(items, newItems, newItemIndex); 
                    items = newItems;
                }
                if (items[newItemIndex] == null) {
                    items[newItemIndex] = new Item(); 
                }
                items[newItemIndex].Set(type, data); 
                lastItem = newItemIndex; 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK