1321 lines
67 KiB
C#
1321 lines
67 KiB
C#
|
//------------------------------------------------------------
|
|||
|
// 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 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* A1 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* A2 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* A3 (<28>) */ 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 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* A6 (<28>) */ 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 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* AB (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* AC (<28>) */ 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 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* B1 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* B2 (<28>) */ 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 (<28>) */ 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 (<28>) */ 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 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* BB (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* BC (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* BD (<28>) */ 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 (<28>) */ 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 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* C5 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* C6 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* C7 (<28>) */ 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 (<28>) */ 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 (<28>) */ 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 (<28>) */ 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 (<28>) */ 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 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* E0 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* E1 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* E2 (<28>) */ 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 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* E5 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* E6 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* E7 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* E8 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* E9 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* EA (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* EB (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* EC (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* ED (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* EE (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* EF (<28>) */ CharType.None|CharType.FirstName|CharType.Name,
|
|||
|
/* F0 (d) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* F1 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* F2 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* F3 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* F4 (<28>) */ 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 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* F7 (<28>) */ 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 (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* FA (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* FB (<28>) */ CharType.None|CharType.Comment|CharType.FirstName|CharType.Name|CharType.Text|CharType.AttributeText,
|
|||
|
/* FC (<28>) */ 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 (<28>) */ 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
|
|||
|
}
|
|||
|
}
|
|||
|
}
|