File: System\Xml\XmlUTF8TextReader.cs
Project: ndp\cdf\src\WCF\Serialization\System.Runtime.Serialization.csproj (System.Runtime.Serialization)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
// Parser
// PERF: Optimize double, decimal?  They get converted to strings in lots of cases
// PERF: Cleanup CharType.  Don't generate tables at runtime.  Use const tables.
 
namespace System.Xml
{
    using System;
    using System.IO;
    using System.Runtime;
    using System.Runtime.Serialization; // For SR
    using System.Text;
 
    public interface IXmlTextReaderInitializer
    {
        void SetInput(byte[] buffer, int offset, int count, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose);
        void SetInput(Stream stream, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose);
    }
 
    class XmlUTF8TextReader : XmlBaseReader, IXmlLineInfo, IXmlTextReaderInitializer
    {
        const int MaxTextChunk = 2048;
        
        PrefixHandle prefix;
        StringHandle localName;
        int[] rowOffsets;
        OnXmlDictionaryReaderClose onClose;
        bool buffered;
        int maxBytesPerRead;
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.StyleCop.CSharp.SpacingRules", "SA1003:SymbolsMustBeSpacedCorrectly", Justification = "Spacing is concise")]
        static byte[] charType = new byte[256]
            {
            /*  0 (.) */ CharType.None,
            /*  1 (.) */ CharType.None,
            /*  2 (.) */ CharType.None,
            /*  3 (.) */ CharType.None,
            /*  4 (.) */ CharType.None,
            /*  5 (.) */ CharType.None,
            /*  6 (.) */ CharType.None,
            /*  7 (.) */ CharType.None,
            /*  8 (.) */ CharType.None,
            /*  9 (.) */ CharType.None|CharType.Comment|CharType.Comment|CharType.Whitespace|CharType.Text|CharType.SpecialWhitespace,
            /*  A (.) */ CharType.None|CharType.Comment|CharType.Comment|CharType.Whitespace|CharType.Text|CharType.SpecialWhitespace,
            /*  B (.) */ CharType.None,
            /*  C (.) */ CharType.None,
            /*  D (.) */ CharType.None|CharType.Comment|CharType.Comment|CharType.Whitespace,
            /*  E (.) */ CharType.None,
            /*  F (.) */ CharType.None,
            /* 10 (.) */ CharType.None,
            /* 11 (.) */ CharType.None,
            /* 12 (.) */ CharType.None,
            /* 13 (.) */ CharType.None,
            /* 14 (.) */ CharType.None,
            /* 15 (.) */ CharType.None,
            /* 16 (.) */ CharType.None,
            /* 17 (.) */ CharType.None,
            /* 18 (.) */ CharType.None,
            /* 19 (.) */ CharType.None,
            /* 1A (.) */ CharType.None,
            /* 1B (.) */ CharType.None,
            /* 1C (.) */ CharType.None,
            /* 1D (.) */ CharType.None,
            /* 1E (.) */ CharType.None,
            /* 1F (.) */ CharType.None,
            /* 20 ( ) */ CharType.None|CharType.Comment|CharType.Whitespace|CharType.Text|CharType.AttributeText|CharType.SpecialWhitespace,
            /* 21 (!) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 22 (") */ CharType.None|CharType.Comment|CharType.Text,
            /* 23 (#) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 24 ($) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 25 (%) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 26 (&) */ CharType.None|CharType.Comment,
            /* 27 (') */ CharType.None|CharType.Comment|CharType.Text,
            /* 28 (() */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 29 ()) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 2A (*) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 2B (+) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 2C (,) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 2D (-) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 2E (.) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 2F (/) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 30 (0) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 31 (1) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 32 (2) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 33 (3) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 34 (4) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 35 (5) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 36 (6) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 37 (7) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 38 (8) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 39 (9) */ CharType.None|CharType.Comment|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 3A (:) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 3B (;) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 3C (<) */ CharType.None|CharType.Comment,
            /* 3D (=) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 3E (>) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 3F (?) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 40 (@) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 41 (A) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 42 (B) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 43 (C) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 44 (D) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 45 (E) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 46 (F) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 47 (G) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 48 (H) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 49 (I) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 4A (J) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 4B (K) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 4C (L) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 4D (M) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 4E (N) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 4F (O) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 50 (P) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 51 (Q) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 52 (R) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 53 (S) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 54 (T) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 55 (U) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 56 (V) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 57 (W) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 58 (X) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 59 (Y) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 5A (Z) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 5B ([) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 5C (\) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 5D (]) */ CharType.None|CharType.Comment|CharType.AttributeText,
            /* 5E (^) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 5F (_) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 60 (`) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 61 (a) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 62 (b) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 63 (c) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 64 (d) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 65 (e) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 66 (f) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 67 (g) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 68 (h) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 69 (i) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 6A (j) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 6B (k) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 6C (l) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 6D (m) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 6E (n) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 6F (o) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 70 (p) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 71 (q) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 72 (r) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 73 (s) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 74 (t) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 75 (u) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 76 (v) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 77 (w) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 78 (x) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 79 (y) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 7A (z) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 7B ({) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 7C (|) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 7D (}) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 7E (~) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 7F (.) */ CharType.None|CharType.Comment|CharType.Text|CharType.AttributeText,
            /* 80 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 81 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 82 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 83 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 84 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 85 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 86 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 87 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 88 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 89 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 8A (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 8B (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 8C (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 8D (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 8E (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 8F (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 90 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 91 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 92 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 93 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 94 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 95 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 96 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 97 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 98 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 99 (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 9A (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 9B (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 9C (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 9D (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 9E (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* 9F (.) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* A0 (ÿ) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* A1 (­) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* A2 (›) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* A3 (œ) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* A4 () */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* A5 () */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* A6 (Ý) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* A7 () */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* A8 (") */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* A9 (c) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* AA (¦) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* AB (®) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* AC (ª) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* AD (-) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* AE (r) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* AF (_) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* B0 (ø) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* B1 (ñ) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* B2 (ý) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* B3 (3) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* B4 (') */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* B5 (æ) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* B6 () */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* B7 (ú) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* B8 (,) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* B9 (1) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* BA (§) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* BB (¯) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* BC (¬) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* BD («) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* BE (_) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* BF (¨) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* C0 (A) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* C1 (A) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* C2 (A) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* C3 (A) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* C4 (Ž) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* C5 () */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* C6 (’) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* C7 (€) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* C8 (E) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* C9 () */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* CA (E) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* CB (E) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* CC (I) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* CD (I) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* CE (I) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* CF (I) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* D0 (D) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* D1 (¥) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* D2 (O) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* D3 (O) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* D4 (O) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* D5 (O) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* D6 (™) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* D7 (x) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* D8 (O) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* D9 (U) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* DA (U) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* DB (U) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* DC (š) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* DD (Y) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* DE (_) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* DF (á) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* E0 (…) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* E1 ( ) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* E2 (ƒ) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* E3 (a) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* E4 („) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* E5 (†) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* E6 (‘) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* E7 (‡) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* E8 (Š) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* E9 (‚) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* EA (ˆ) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* EB (‰) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* EC () */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* ED (¡) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* EE (Œ) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* EF (‹) */ CharType.None|CharType.FirstName|CharType.Name,
            /* F0 (d) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* F1 (¤) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* F2 (•) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* F3 (¢) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* F4 (“) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* F5 (o) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* F6 (”) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* F7 (ö) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* F8 (o) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* F9 (—) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* FA (£) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* FB (–) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* FC () */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* FD (y) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* FE (_) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            /* FF (˜) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
            };
 
        public XmlUTF8TextReader()
        {
            this.prefix = new PrefixHandle(BufferReader);
            this.localName = new StringHandle(BufferReader);
#if GENERATE_CHARTYPE
            CharType.Generate();
#endif
        }
 
        public void SetInput(byte[] buffer, int offset, int count, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)
        {
            if (buffer == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer"));
            if (offset < 0)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
            if (offset > buffer.Length)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, buffer.Length)));
            if (count < 0)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
            if (count > buffer.Length - offset)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset)));
            MoveToInitial(quotas, onClose);
            ArraySegment<byte> seg = EncodingStreamWrapper.ProcessBuffer(buffer, offset, count, encoding);
            BufferReader.SetBuffer(seg.Array, seg.Offset, seg.Count, null, null);
            this.buffered = true;
        }
 
        public void SetInput(Stream stream, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)
        {
            if (stream == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
            MoveToInitial(quotas, onClose);
            stream = new EncodingStreamWrapper(stream, encoding);
            BufferReader.SetBuffer(stream, null, null);
            this.buffered = false;
        }
 
        void MoveToInitial(XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)
        {
            MoveToInitial(quotas);
            this.maxBytesPerRead = quotas.MaxBytesPerRead;
            this.onClose = onClose;
        }
 
        public override void Close()
        {
            rowOffsets = null;
            base.Close();
            OnXmlDictionaryReaderClose onClose = this.onClose;
            this.onClose = null;
            if (onClose != null)
            {
                try
                {
                    onClose(this);
                }
                catch (Exception e)
                {
                    if (Fx.IsFatal(e)) throw;
 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
                }
            }
        }
 
        void SkipWhitespace()
        {
            while (!BufferReader.EndOfFile && (charType[BufferReader.GetByte()] & CharType.Whitespace) != 0)
                BufferReader.SkipByte();
        }
 
        void ReadDeclaration()
        {
            if (!buffered)
                BufferElement();
            int offset;
            byte[] buffer = BufferReader.GetBuffer(5, out offset);
            if (buffer[offset + 0] != (byte)'?' ||
                buffer[offset + 1] != (byte)'x' ||
                buffer[offset + 2] != (byte)'m' ||
                buffer[offset + 3] != (byte)'l' ||
                (charType[buffer[offset + 4]] & CharType.Whitespace) == 0)
            {
                XmlExceptionHelper.ThrowProcessingInstructionNotSupported(this);
            }
            // If anything came before the "<?xml ?>" it's an error.
            if (this.Node.ReadState != ReadState.Initial)
            {
                XmlExceptionHelper.ThrowDeclarationNotFirst(this);
            }
            BufferReader.Advance(5);
 
            int localNameOffset = offset + 1;
            int localNameLength = 3;
 
            int valueOffset = BufferReader.Offset;
            SkipWhitespace();
            ReadAttributes();
            int valueLength = BufferReader.Offset - valueOffset;
 
            // Backoff the spaces
            while (valueLength > 0)
            {
                byte ch = BufferReader.GetByte(valueOffset + valueLength - 1);
                    if ((charType[ch] & CharType.Whitespace) == 0)
                    break;
                valueLength--;
            }
 
            buffer = BufferReader.GetBuffer(2, out offset);
            if (buffer[offset + 0] != (byte)'?' ||
                buffer[offset + 1] != (byte)'>')
            {
                XmlExceptionHelper.ThrowTokenExpected(this, "?>", Encoding.UTF8.GetString(buffer, offset, 2));
            }
            BufferReader.Advance(2);
            XmlDeclarationNode declarationNode = MoveToDeclaration();
            declarationNode.LocalName.SetValue(localNameOffset, localNameLength);
            declarationNode.Value.SetValue(ValueHandleType.UTF8, valueOffset, valueLength);
        }
 
        void VerifyNCName(string s)
        {
            try
            {
                XmlConvert.VerifyNCName(s);
            }
            catch (XmlException exception)
            {
                XmlExceptionHelper.ThrowXmlException(this, exception);
            }
        }
 
        void ReadQualifiedName(PrefixHandle prefix, StringHandle localName)
        {
            int offset;
            int offsetMax;
            byte[] buffer = BufferReader.GetBuffer(out offset, out offsetMax);
 
            int ch = 0;
            int anyChar = 0;
            int prefixChar = 0;
            int prefixOffset = offset;
            if (offset < offsetMax)
            {
                ch = buffer[offset];
                prefixChar = ch;
                if ((charType[ch] & CharType.FirstName) == 0)
                    anyChar |= 0x80;
                anyChar |= ch;
                offset++;
                while (offset < offsetMax)
                {
                    ch = buffer[offset];
                    if ((charType[ch] & CharType.Name) == 0)
                        break;
                    anyChar |= ch;
                    offset++;
                }
            }
            else
            {
                anyChar |= 0x80;
                ch = 0;
            }
            if (ch == ':')
            {
                int prefixLength = offset - prefixOffset;
                if (prefixLength == 1 && prefixChar >= 'a' && prefixChar <= 'z')
                    prefix.SetValue(PrefixHandle.GetAlphaPrefix(prefixChar - 'a'));
                else
                    prefix.SetValue(prefixOffset, prefixLength);
 
                offset++;
                int localNameOffset = offset;
                if (offset < offsetMax)
                {
                    ch = buffer[offset];
                    if ((charType[ch] & CharType.FirstName) == 0)
                        anyChar |= 0x80;
                    anyChar |= ch;
                    offset++;
                    while (offset < offsetMax)
                    {
                        ch = buffer[offset];
                        if ((charType[ch] & CharType.Name) == 0)
                            break;
                        anyChar |= ch;
                        offset++;
                    }
                }
                else
                {
                    anyChar |= 0x80;
                    ch = 0;
                }
                localName.SetValue(localNameOffset, offset - localNameOffset);
                if (anyChar >= 0x80)
                {
                    VerifyNCName(prefix.GetString());
                    VerifyNCName(localName.GetString());
                }
            }
            else
            {
                prefix.SetValue(PrefixHandleType.Empty);
                localName.SetValue(prefixOffset, offset - prefixOffset);
                if (anyChar >= 0x80)
                {
                    VerifyNCName(localName.GetString());
                }
            }
            BufferReader.Advance(offset - prefixOffset);
        }
 
        int ReadAttributeText(byte[] buffer, int offset, int offsetMax)
        {
            byte[] charType = XmlUTF8TextReader.charType;
            int textOffset = offset;
            while (offset < offsetMax && (charType[buffer[offset]] & CharType.AttributeText) != 0)
                offset++;
            return offset - textOffset;
        }
 
        void ReadAttributes()
        {
            int startOffset = 0;
            if (buffered)
                startOffset = BufferReader.Offset;
            
            while (true)
            {
                byte ch;
                ReadQualifiedName(prefix, localName);
                if (BufferReader.GetByte() != '=')
                {
                    SkipWhitespace();
                    if (BufferReader.GetByte() != '=')
                        XmlExceptionHelper.ThrowTokenExpected(this, "=", (char)BufferReader.GetByte());
                }
                BufferReader.SkipByte();
                byte quoteChar = BufferReader.GetByte();
                if (quoteChar != '"' && quoteChar != '\'')
                {
                    SkipWhitespace();
                    quoteChar = BufferReader.GetByte();
                    if (quoteChar != '"' && quoteChar != '\'')
                        XmlExceptionHelper.ThrowTokenExpected(this, "\"", (char)BufferReader.GetByte());
                }
                BufferReader.SkipByte();
                bool escaped = false;
                int valueOffset = BufferReader.Offset;
                while (true)
                {
                    int offset, offsetMax;
                    byte[] buffer = BufferReader.GetBuffer(out offset, out offsetMax);
                    int length = ReadAttributeText(buffer, offset, offsetMax);
                    BufferReader.Advance(length);
                    ch = BufferReader.GetByte();
                    if (ch == quoteChar)
                        break;
                    if (ch == '&')
                    {
                        ReadCharRef();
                        escaped = true;
                    }
                    else if (ch == '\'' || ch == '"')
                    {
                        BufferReader.SkipByte();
                    }
                    else if (ch == '\n' || ch == '\r' || ch == '\t')
                    {
                        BufferReader.SkipByte();
                        escaped = true;
                    }
                    else if (ch == 0xEF)
                    {
                        ReadNonFFFE();
                    }
                    else
                    {
                        XmlExceptionHelper.ThrowTokenExpected(this, ((char)quoteChar).ToString(), (char)ch);
                    }
                }
                int valueLength = BufferReader.Offset - valueOffset;
 
                XmlAttributeNode attributeNode;
                if (prefix.IsXmlns)
                {
                    Namespace ns = AddNamespace();
                    localName.ToPrefixHandle(ns.Prefix);
                    ns.Uri.SetValue(valueOffset, valueLength, escaped);
                    attributeNode = AddXmlnsAttribute(ns);
                }
                else if (prefix.IsEmpty && localName.IsXmlns)
                {
                    Namespace ns = AddNamespace();
                    ns.Prefix.SetValue(PrefixHandleType.Empty);
                    ns.Uri.SetValue(valueOffset, valueLength, escaped);
                    attributeNode = AddXmlnsAttribute(ns);
                }
                else if (prefix.IsXml)
                {
                    attributeNode = AddXmlAttribute();
                    attributeNode.Prefix.SetValue(prefix);
                    attributeNode.LocalName.SetValue(localName);
                    attributeNode.Value.SetValue((escaped ? ValueHandleType.EscapedUTF8 : ValueHandleType.UTF8), valueOffset, valueLength);
                    FixXmlAttribute(attributeNode);
                }
                else
                {
                    attributeNode = AddAttribute();
                    attributeNode.Prefix.SetValue(prefix);
                    attributeNode.LocalName.SetValue(localName);
                    attributeNode.Value.SetValue((escaped ? ValueHandleType.EscapedUTF8 : ValueHandleType.UTF8), valueOffset, valueLength);
                }
 
                attributeNode.QuoteChar = (char)quoteChar;
                BufferReader.SkipByte();
                
                ch = BufferReader.GetByte();
                
                bool space = false;
                while ((charType[ch] & CharType.Whitespace) != 0)
                {
                    space = true;
                    BufferReader.SkipByte();
                    ch = BufferReader.GetByte();
                }
 
                if (ch == '>' || ch == '/' || ch == '?')
                    break;
 
                if (!space)
                    XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlSpaceBetweenAttributes)));
            }
 
            if (buffered && (BufferReader.Offset - startOffset) > this.maxBytesPerRead)
                XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(this, this.maxBytesPerRead);
 
            ProcessAttributes();
        }
 
        void ReadNonFFFE()
        {
            int off;
            byte[] buff = BufferReader.GetBuffer(3, out off);
            if (buff[off + 1] == 0xBF && (buff[off + 2] == 0xBE || buff[off + 2] == 0xBF))
            {
                XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlInvalidFFFE)));
            }
            BufferReader.Advance(3);
        }
 
        // NOTE: Call only if 0xEF has been seen in the stream AND there are three valid bytes to check (buffer[offset], buffer[offset + 1], buffer[offset + 2]). 
        // 0xFFFE and 0xFFFF are not valid characters per Unicode specification. The first byte in the UTF8 representation is 0xEF. 
        bool IsNextCharacterNonFFFE(byte[] buffer, int offset)
        {
            Fx.Assert(buffer[offset] == 0xEF, "buffer[offset] MUST be 0xEF."); 
 
            if (buffer[offset + 1] == 0xBF && (buffer[offset + 2] == 0xBE || buffer[offset + 2] == 0xBF))
            {
                // 0xFFFE : 0xEF 0xBF 0xBE
                // 0xFFFF : 0xEF 0xBF 0xBF
                // we know that buffer[offset] is already 0xEF, don't bother checking it.
                return false;
            }
 
            // no bad characters
            return true;
        }
 
        void BufferElement()
        {
            int elementOffset = BufferReader.Offset;
            const int byteCount = 128;
            bool done = false;
            byte quoteChar = 0;
            while (!done)
            {
                int offset;
                int offsetMax;
                byte[] buffer = BufferReader.GetBuffer(byteCount, out offset, out offsetMax);
                if (offset + byteCount != offsetMax)
                    break;
                for (int i = offset; i < offsetMax && !done; i++)
                {
                    byte b = buffer[i];
                    if (quoteChar == 0)
                    {
                        if (b == '\'' || b == '"')
                            quoteChar = b;
                        if (b == '>')
                            done = true;
                    }
                    else
                    {
                        if (b == quoteChar)
                        {
                            quoteChar = 0;
                        }
                    }
                }
                BufferReader.Advance(byteCount);
            }
            BufferReader.Offset = elementOffset;
        }
 
        new void ReadStartElement()
        {
            if (!buffered)
                BufferElement();
            XmlElementNode elementNode = EnterScope();
            elementNode.NameOffset = BufferReader.Offset;
            ReadQualifiedName(elementNode.Prefix, elementNode.LocalName);
            elementNode.NameLength = BufferReader.Offset - elementNode.NameOffset;
            byte ch = BufferReader.GetByte();
            while ((charType[ch] & CharType.Whitespace) != 0)
            {
                BufferReader.SkipByte();
                ch = BufferReader.GetByte();
            }
            if (ch != '>' && ch != '/')
            {
                ReadAttributes();
                ch = BufferReader.GetByte();
            }
            elementNode.Namespace = LookupNamespace(elementNode.Prefix);
            bool isEmptyElement = false;
            if (ch == '/')
            {
                isEmptyElement = true;
                BufferReader.SkipByte();
            }
            elementNode.IsEmptyElement = isEmptyElement;
            elementNode.ExitScope = isEmptyElement;
            if (BufferReader.GetByte() != '>')
                XmlExceptionHelper.ThrowTokenExpected(this, ">", (char)BufferReader.GetByte());
            BufferReader.SkipByte();
            elementNode.BufferOffset = BufferReader.Offset;
        }
 
        new void ReadEndElement()
        {
            BufferReader.SkipByte();
            XmlElementNode elementNode = this.ElementNode;
            int nameOffset = elementNode.NameOffset;
            int nameLength = elementNode.NameLength;
            int offset;
            byte[] buffer = BufferReader.GetBuffer(nameLength, out offset);
            for (int i = 0; i < nameLength; i++)
            {
                if (buffer[offset + i] != buffer[nameOffset + i])
                {
                    ReadQualifiedName(prefix, localName);
                    XmlExceptionHelper.ThrowTagMismatch(this, elementNode.Prefix.GetString(), elementNode.LocalName.GetString(), prefix.GetString(), localName.GetString());
                }
            }
            BufferReader.Advance(nameLength);
            if (BufferReader.GetByte() != '>')
            {
                SkipWhitespace();
                if (BufferReader.GetByte() != '>')
                    XmlExceptionHelper.ThrowTokenExpected(this, ">", (char)BufferReader.GetByte());
            }
            BufferReader.SkipByte();
            MoveToEndElement();
        }
 
        void ReadComment()
        {
            BufferReader.SkipByte();
            if (BufferReader.GetByte() != '-')
                XmlExceptionHelper.ThrowTokenExpected(this, "--", (char)BufferReader.GetByte());
            BufferReader.SkipByte();
            int commentOffset = BufferReader.Offset;
            while (true)
            {
                while (true)
                {
                    byte b = BufferReader.GetByte();
                    if (b == '-')
                        break;
                    if ((charType[b] & CharType.Comment) == 0)
                    {
                        if (b == 0xEF)
                            ReadNonFFFE();
                        else
                            XmlExceptionHelper.ThrowInvalidXml(this, b);
                    }
                    else
                    {
                        BufferReader.SkipByte();
                    }
                }
 
                int offset;
                byte[] buffer = BufferReader.GetBuffer(3, out offset);
                if (buffer[offset + 0] == (byte)'-' &&
                    buffer[offset + 1] == (byte)'-')
                { 
                    if (buffer[offset + 2] == (byte)'>')
                        break;
                    XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlInvalidCommentChars)));
                }
                BufferReader.SkipByte();
            }
            int commentLength = BufferReader.Offset - commentOffset;
            MoveToComment().Value.SetValue(ValueHandleType.UTF8, commentOffset, commentLength);
            BufferReader.Advance(3);
        }
 
        void ReadCData()
        {
            int offset;
            byte[] buffer = BufferReader.GetBuffer(7, out offset);
            if (buffer[offset + 0] != (byte)'[' ||
                buffer[offset + 1] != (byte)'C' ||
                buffer[offset + 2] != (byte)'D' ||
                buffer[offset + 3] != (byte)'A' ||
                buffer[offset + 4] != (byte)'T' ||
                buffer[offset + 5] != (byte)'A' ||
                buffer[offset + 6] != (byte)'[')
            {
                XmlExceptionHelper.ThrowTokenExpected(this, "[CDATA[", Encoding.UTF8.GetString(buffer, offset, 7));
            }
            BufferReader.Advance(7);
            int cdataOffset = BufferReader.Offset;
            while (true)
            {
                byte b;
                while (true)
                {
                    b = BufferReader.GetByte();
                    if (b == ']')
                        break;
 
                    if (b == 0xEF)
                        ReadNonFFFE();
                    else
                        BufferReader.SkipByte();
                }
                buffer = BufferReader.GetBuffer(3, out offset);
                if (buffer[offset + 0] == (byte)']' &&
                    buffer[offset + 1] == (byte)']' &&
                    buffer[offset + 2] == (byte)'>')
                    break;
                BufferReader.SkipByte();
            }
            int cdataLength = BufferReader.Offset - cdataOffset;
            MoveToCData().Value.SetValue(ValueHandleType.UTF8, cdataOffset, cdataLength);
            BufferReader.Advance(3);
        }
 
        int ReadCharRef()
        {
            Fx.Assert(BufferReader.GetByte() == '&', "");
            int charEntityOffset = BufferReader.Offset;
            BufferReader.SkipByte();
            while (BufferReader.GetByte() != ';')
                BufferReader.SkipByte();
            BufferReader.SkipByte();
            int charEntityLength = BufferReader.Offset - charEntityOffset;
            BufferReader.Offset = charEntityOffset;
            int ch = BufferReader.GetCharEntity(charEntityOffset, charEntityLength);
            BufferReader.Advance(charEntityLength);
            return ch;
        }
 
 
        void ReadWhitespace()
        {
            byte[] buffer;
            int offset;
            int offsetMax;
            int length;
            
            if (buffered)
            {
                buffer = BufferReader.GetBuffer(out offset, out offsetMax);
                length = ReadWhitespace(buffer, offset, offsetMax);
            }
            else
            {
                buffer = BufferReader.GetBuffer(MaxTextChunk, out offset, out offsetMax);
                length = ReadWhitespace(buffer, offset, offsetMax);
                length = BreakText(buffer, offset, length);
            }
            BufferReader.Advance(length);
 
            MoveToWhitespaceText().Value.SetValue(ValueHandleType.UTF8, offset, length);
        }
 
        int ReadWhitespace(byte[] buffer, int offset, int offsetMax)
        {
            byte[] charType = XmlUTF8TextReader.charType;
            int wsOffset = offset;
            while (offset < offsetMax && (charType[buffer[offset]] & CharType.SpecialWhitespace) != 0)
                offset++;
            return offset - wsOffset;
        }
 
        int ReadText(byte[] buffer, int offset, int offsetMax)
        {
            byte[] charType = XmlUTF8TextReader.charType;
            int textOffset = offset;
            while (offset < offsetMax && (charType[buffer[offset]] & CharType.Text) != 0)
                offset++; 
            return offset - textOffset;
        }
 
        // Read Unicode codepoints 0xFvvv
        int ReadTextAndWatchForInvalidCharacters(byte[] buffer, int offset, int offsetMax)
        {
            byte[] charType = XmlUTF8TextReader.charType;
            int textOffset = offset;
 
            while (offset < offsetMax && ((charType[buffer[offset]] & CharType.Text) != 0 || buffer[offset] == 0xEF))
            {
                if (buffer[offset] != 0xEF)
                {
                    offset++;
                }
                else
                {
                    // Ensure that we have three bytes (buffer[offset], buffer[offset + 1], buffer[offset + 2])  
                    // available for IsNextCharacterNonFFFE to check. 
                    if (offset + 2 < offsetMax) 
                    {
                        if (IsNextCharacterNonFFFE(buffer, offset))
                        {
                            // if first byte is 0xEF, UTF8 mandates a 3-byte character representation of this Unicode code point
                            offset += 3;
                        }
                        else
                        {
                            XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlInvalidFFFE)));
                        }
                    } 
                    else 
                    {
                        if (BufferReader.Offset < offset)
                        {
                            // We have read some characters already
                            // Let the outer ReadText advance the bufferReader and return text node to caller
                            break;
                        }
                        else
                        {
                            // Get enough bytes for us to process next character, then go back to top of while loop
                            int dummy;
                            BufferReader.GetBuffer(3, out dummy);
                        }
                    }
                }
            }
            return offset - textOffset;
        }
 
        // bytes   bits    UTF-8 representation
        // -----   ----    -----------------------------------
        // 1        7      0vvvvvvv
        // 2       11      110vvvvv 10vvvvvv
        // 3       16      1110vvvv 10vvvvvv 10vvvvvv
        // 4       21      11110vvv 10vvvvvv 10vvvvvv 10vvvvvv
        // -----   ----    -----------------------------------
 
        int BreakText(byte[] buffer, int offset, int length)
        {
            // See if we might be breaking a utf8 sequence
            if (length > 0 && (buffer[offset + length - 1] & 0x80) == 0x80)
            {
                // Find the lead char of the utf8 sequence (0x11xxxxxx)
                int originalLength = length;
                do
                {
                    length--;
                }
                while (length > 0 && (buffer[offset + length] & 0xC0) != 0xC0);
                // Couldn't find the lead char
                if (length == 0)
                    return originalLength; // Invalid utf8 sequence - can't break
                // Count how many bytes follow the lead char
                byte b = (byte)(buffer[offset + length] << 2);
                int byteCount = 2;
                while ((b & 0x80) == 0x80)
                {
                    b = (byte)(b << 1);
                    byteCount++;
                    // There shouldn't be more than 3 bytes following the lead char
                    if (byteCount > 4)
                        return originalLength; // Invalid utf8 sequence - can't break
                }
                if (length + byteCount == originalLength)
                    return originalLength; // sequence fits exactly
                if (length == 0)
                    return originalLength; // Quota too small to read a char
            }
            return length;
        }
 
        void ReadText(bool hasLeadingByteOf0xEF)
        {
            byte[] buffer;
            int offset;
            int offsetMax;
            int length;
            
            if (buffered)
            {
                buffer = BufferReader.GetBuffer(out offset, out offsetMax);
                if (hasLeadingByteOf0xEF)
                {
                    length = ReadTextAndWatchForInvalidCharacters(buffer, offset, offsetMax); 
                }
                else
                {
                    length = ReadText(buffer, offset, offsetMax); 
                }
            }
            else
            {
                buffer = BufferReader.GetBuffer(MaxTextChunk, out offset, out offsetMax);
                if (hasLeadingByteOf0xEF)
                {
                    length = ReadTextAndWatchForInvalidCharacters(buffer, offset, offsetMax); 
                }
                else
                {
                    length = ReadText(buffer, offset, offsetMax);
                }
                length = BreakText(buffer, offset, length);
            }
            BufferReader.Advance(length);
            
            if (offset < offsetMax - 1 - length && (buffer[offset + length] == (byte)'<' && buffer[offset + length + 1] != (byte)'!'))
            {
                MoveToAtomicText().Value.SetValue(ValueHandleType.UTF8, offset, length);
            }
            else
            {
                MoveToComplexText().Value.SetValue(ValueHandleType.UTF8, offset, length);
            }
        }
 
        void ReadEscapedText()
        {
            int ch = ReadCharRef();
            if (ch < 256 && (charType[ch] & CharType.Whitespace) != 0)
                MoveToWhitespaceText().Value.SetCharValue(ch);
            else
                MoveToComplexText().Value.SetCharValue(ch);
        }
 
        public override bool Read()
        {
            if (this.Node.ReadState == ReadState.Closed)
                return false;
 
            if (this.Node.CanMoveToElement)
            {
                // If we're positioned on an attribute or attribute text on an empty element, we need to move back
                // to the element in order to get the correct setting of ExitScope
                MoveToElement();
            }
            SignNode();
            if (this.Node.ExitScope)
            {
                ExitScope();
            }
            if (!buffered)
                BufferReader.SetWindow(ElementNode.BufferOffset, this.maxBytesPerRead);
 
            if (BufferReader.EndOfFile)
            {
                MoveToEndOfFile();
                return false;
            }
            byte ch = BufferReader.GetByte();
            if (ch == (byte)'<')
            {
                BufferReader.SkipByte();
                ch = BufferReader.GetByte();
                if (ch == (byte)'/')
                    ReadEndElement();
                else if (ch == (byte)'!')
                {
                    BufferReader.SkipByte();
                    ch = BufferReader.GetByte();
                    if (ch == '-')
                    {
                        ReadComment();
                    }
                    else
                    {
                        if (OutsideRootElement)
                            XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlCDATAInvalidAtTopLevel)));
                            
                        ReadCData();
                    }
                }
                else if (ch == (byte)'?')
                    ReadDeclaration();
                else
                    ReadStartElement();
            }
            else if ((charType[ch] & CharType.SpecialWhitespace) != 0)
            {
                ReadWhitespace();
            }
            else if (OutsideRootElement && ch != '\r')
            {
                XmlExceptionHelper.ThrowInvalidRootData(this);
            }
            else if ((charType[ch] & CharType.Text) != 0)
            {
                ReadText(false);
            }
            else if (ch == '&')
            {
                ReadEscapedText();
            }
            else if (ch == '\r')
            {
                BufferReader.SkipByte();
 
                if (!BufferReader.EndOfFile && BufferReader.GetByte() == '\n')
                    ReadWhitespace();
                else
                    MoveToComplexText().Value.SetCharValue('\n');
            }
            else if (ch == ']')
            {
                int offset;
                byte[] buffer = BufferReader.GetBuffer(3, out offset);
                if (buffer[offset + 0] == (byte)']' &&
                    buffer[offset + 1] == (byte)']' &&
                    buffer[offset + 2] == (byte)'>')
                {
                    XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlCloseCData)));
                }
 
                BufferReader.SkipByte();
                MoveToComplexText().Value.SetCharValue(']');  // Need to get past the ']' and keep going.
            }
            else if (ch == 0xEF)  // Watch for invalid characters 0xfffe and 0xffff
            {
                ReadText(true);
            }
            else
            {
                XmlExceptionHelper.ThrowInvalidXml(this, ch);
            }
            return true;
        }
 
        protected override XmlSigningNodeWriter CreateSigningNodeWriter()
        {
            return new XmlSigningNodeWriter(true);
        }
 
        public bool HasLineInfo()
        {
            return true;
        }
 
        public int LineNumber
        {
            get
            {
                int row, column;
                GetPosition(out row, out column);
                return row;
            }
        }
 
        public int LinePosition
        {
            get
            {
                int row, column;
                GetPosition(out row, out column);
                return column;
            }
        }
 
        void GetPosition(out int row, out int column)
        {
            if (rowOffsets == null)
            {
                rowOffsets = BufferReader.GetRows();
            }
 
            int offset = BufferReader.Offset;
 
            int j = 0;
            while (j < rowOffsets.Length - 1 && rowOffsets[j + 1] < offset)
                j++;
 
            row = j + 1;
            column = offset - rowOffsets[j] + 1;
        }
 
        static class CharType
        {
            public const byte None = 0x00;
            public const byte FirstName = 0x01;
            public const byte Name = 0x02;
            public const byte Whitespace = 0x04;
            public const byte Text = 0x08;
            public const byte AttributeText = 0x10;
            public const byte SpecialWhitespace = 0x20;
            public const byte Comment = 0x40;
 
#if GENERATE_CHARTYPE
            static public void Generate()
            {
                bool[] isFirstNameChar = new bool[256];
                bool[] isNameChar = new bool[256];
                bool[] isSpaceChar = new bool[256];
                bool[] isSpecialSpaceChar = new bool[256];
                bool[] isTextChar = new bool[256];
                bool[] isAttributeTextChar = new bool[256];
 
                for (int i = 0; i < 256; i++)
                {
                    isFirstNameChar[i] = false;
                    isNameChar[i] = false;
                    isSpaceChar[i] = false;
                    isTextChar[i] = false;
                    isSpecialSpaceChar[i] = false;
                }
 
                for (int i = 'A'; i <= 'Z'; i++)
                {
                    isFirstNameChar[i] = true;
                    isFirstNameChar[i + 32] = true;
                }
 
                isFirstNameChar['_'] = true;
 
                // Allow utf8 chars as the first char
                for (int i = 128; i < 256; i++)
                {
                    isFirstNameChar[i] = true;
                }
 
                for (int i = 'A'; i <= 'Z'; i++)
                {
                    isNameChar[i] = true;
                    isNameChar[i + 32] = true;
                }
 
                for (int i = '0'; i <= '9'; i++)
                    isNameChar[i] = true;
 
                isNameChar['_'] = true;
                isNameChar['.'] = true;
                isNameChar['-'] = true;
 
                for (int i = 128; i < 256; i++)
                {
                    isNameChar[i] = true;
                }
 
                isSpaceChar[' '] = true;
                isSpaceChar[0x09] = true;
                isSpaceChar[0x0D] = true;
                isSpaceChar[0x0A] = true;
 
                isSpecialSpaceChar[' '] = true;
                isSpecialSpaceChar[0x09] = true;
                isSpecialSpaceChar[0x0A] = true;
 
                for (int i = 32; i < 128; i++)
                    isTextChar[i] = true;
 
                isTextChar[0x09] = true;
                isTextChar[0x0D] = false;
                isTextChar[0x0A] = true;
                isTextChar['<'] = false;
                isTextChar['&'] = false;
                isTextChar[']'] = false;
 
                for (int i = 128; i < 256; i++)
                    isTextChar[i] = true;
 
                for (int i = 0; i < 256; i++)
                {
                    isAttributeTextChar[i] = isTextChar[i];
                }
 
                isAttributeTextChar[0x09] = false;
                isAttributeTextChar[0x0D] = false;
                isAttributeTextChar[0x0A] = false;
                isAttributeTextChar[']'] = true;
                isAttributeTextChar['\''] = false;
                isAttributeTextChar['"'] = false;
 
                for (int i = 0; i < 256; i++)
                {
                    Console.Write("            /* {0,2:X} ({1}) */ CharType.None", i, char.IsControl((char)i) ? '.' : (char)i);
                    if (isFirstNameChar[i])
                        Console.Write("|CharType.FirstName");
 
                    if (isNameChar[i])
                        Console.Write("|CharType.Name");
 
                    if (isSpaceChar[i])
                        Console.Write("|CharType.Whitespace");
 
                    if (isTextChar[i])
                        Console.Write("|CharType.Text");
 
                    if (isAttributeTextChar[i])
                        Console.Write("|CharType.AttributeText");
 
                    if (isSpecialSpaceChar[i])
                        Console.Write("|CharType.SpecialWhitespace");
 
                    Console.WriteLine(",");
                }
            }
#endif
        }
    }
}