* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / corlib / Mono.Xml / MiniParser.cs
1 //
2 // System.Security.Cryptography.MiniParser: Internal XML parser implementation
3 //
4 // Authors:
5 //      Sergey Chaban
6 //
7 // Copyright (c) 2001, 2002 Wild West Software
8 // Copyright (c) 2002 Sergey Chaban
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Text;
33 using System.Collections;
34 using System.Globalization;
35
36 namespace Mono.Xml {
37
38 #if INSIDE_CORLIB
39         internal
40 #else
41         [CLSCompliant(false)]    
42         public
43 #endif
44 class MiniParser {
45
46         public interface IReader {
47                 int Read();
48         }
49
50         public interface IAttrList {
51                 int Length {get;}
52                 bool IsEmpty {get;}
53                 string GetName(int i);
54                 string GetValue(int i);
55                 string GetValue(string name);
56                 void ChangeValue(string name, string newValue);
57                 string[] Names {get;}
58                 string[] Values {get;}
59         }
60
61         public interface IMutableAttrList : IAttrList {
62                 void Clear();
63                 void Add(string name, string value);
64                 void CopyFrom(IAttrList attrs);
65                 void Remove(int i);
66                 void Remove(string name);
67         }
68
69         public interface IHandler {
70                 void OnStartParsing(MiniParser parser);
71                 void OnStartElement(string name, IAttrList attrs);
72                 void OnEndElement(string name);
73                 void OnChars(string ch);
74                 void OnEndParsing(MiniParser parser);
75         }
76
77         public class HandlerAdapter : IHandler {
78                 public HandlerAdapter() {}
79                 public void OnStartParsing(MiniParser parser) {}
80                 public void OnStartElement(string name, IAttrList attrs) {}
81                 public void OnEndElement(string name) {}
82                 public void OnChars(string ch) {}
83                 public void OnEndParsing(MiniParser parser) {}
84         }
85
86         private enum CharKind : byte {
87                 LEFT_BR     = 0,
88                 RIGHT_BR    = 1,
89                 SLASH       = 2,
90                 PI_MARK     = 3,
91                 EQ          = 4,
92                 AMP         = 5,
93                 SQUOTE      = 6,
94                 DQUOTE      = 7,
95                 BANG        = 8,
96                 LEFT_SQBR   = 9,
97                 SPACE       = 0xA,
98                 RIGHT_SQBR  = 0xB,
99                 TAB         = 0xC,
100                 CR          = 0xD,
101                 EOL         = 0xE,
102                 CHARS       = 0xF,
103                 UNKNOWN = 0x1F
104         }
105
106         private enum ActionCode : byte {
107                 START_ELEM               = 0,
108                 END_ELEM                 = 1,
109                 END_NAME                 = 2,
110                 SET_ATTR_NAME            = 3,
111                 SET_ATTR_VAL             = 4,
112                 SEND_CHARS               = 5,
113                 START_CDATA              = 6,
114                 END_CDATA                = 7,
115                 ERROR                    = 8,
116                 STATE_CHANGE             = 9,
117                 FLUSH_CHARS_STATE_CHANGE = 0xA,
118                 ACC_CHARS_STATE_CHANGE   = 0xB,
119                 ACC_CDATA                = 0xC,
120                 PROC_CHAR_REF            = 0xD,
121                 UNKNOWN = 0xF
122         }
123
124         public class AttrListImpl : IMutableAttrList {
125                 protected ArrayList names;
126                 protected ArrayList values;
127
128                 public AttrListImpl() : this(0) {}
129
130                 public AttrListImpl(int initialCapacity) {
131                         if (initialCapacity <= 0) {
132                                 names = new ArrayList();
133                                 values = new ArrayList();
134                         } else {
135                                 names = new ArrayList(initialCapacity);
136                                 values = new ArrayList(initialCapacity);
137                         }
138                 }
139
140                 public AttrListImpl(IAttrList attrs)
141                 : this(attrs != null ? attrs.Length : 0) {
142                         if (attrs != null) this.CopyFrom(attrs);
143                 }
144
145                 public int Length {
146                         get {return names.Count;}
147                 }
148
149                 public bool IsEmpty {
150                         get {return this.Length != 0;}
151                 }
152
153                 public string GetName(int i) {
154                         string res = null;
155                         if (i >= 0 && i < this.Length) {
156                                 res = names[i] as string;
157                         }
158                         return res;
159                 }
160
161                 public string GetValue(int i) {
162                         string res = null;
163                         if (i >= 0 && i < this.Length) {
164                                 res = values[i] as string;
165                         }
166                         return res;
167                 }
168
169                 public string GetValue(string name) {
170                         return this.GetValue(names.IndexOf(name));
171                 }
172
173                 public void ChangeValue(string name, string newValue) {
174                         int i = names.IndexOf(name);
175                         if (i >= 0 && i < this.Length) {
176                                 values[i] = newValue;
177                         }
178                 }
179
180                 public string[] Names {
181                         get {return names.ToArray(typeof(string)) as string[];}
182                 }
183
184                 public string[] Values {
185                         get {return values.ToArray(typeof(string)) as string[];}
186                 }
187
188                 public void Clear() {
189                         names.Clear();
190                         values.Clear();
191                 }
192
193                 public void Add(string name, string value) {
194                         names.Add(name);
195                         values.Add(value);
196                 }
197
198                 public void Remove(int i) {
199                         if (i >= 0) {
200                                 names.RemoveAt(i);
201                                 values.RemoveAt(i);
202                         }
203                 }
204
205                 public void Remove(string name) {
206                         this.Remove(names.IndexOf(name));
207                 }
208
209                 public void CopyFrom(IAttrList attrs) {
210                         if (attrs != null && ((object)this == (object)attrs)) {
211                                 this.Clear();
212                                 int n = attrs.Length;
213                                 for (int i = 0; i < n; i++) {
214                                         this.Add(attrs.GetName(i), attrs.GetValue(i));
215                                 }
216                         }
217                 }
218         }
219
220         public class XMLError : Exception {
221                 protected string descr;
222                 protected int line, column;
223                 public XMLError() : this("Unknown") {}
224                 public XMLError(string descr) : this(descr, -1, -1) {}
225                 public XMLError(string descr, int line, int column)
226                 : base(descr) {
227                         this.descr = descr;
228                         this.line = line;
229                         this.column = column;
230                 }
231                 public int Line {get {return line;}}
232                 public int Column {get {return column;}}
233                 public override string ToString() {
234                         return (String.Format("{0} @ (line = {1}, col = {2})", descr, line, column));
235                 }
236         }
237
238         private static readonly int INPUT_RANGE = 13;
239         private static readonly ushort[] tbl = {
240                 (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 1), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 0), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ERROR << 8) | 128), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ERROR << 8) | 128), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 128), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ERROR << 8) | 128), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ERROR << 8) | 128), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 128), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 128), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ERROR << 8) | 128), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 128), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 128), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 128),
241                 (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 2), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 133), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 16), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.FLUSH_CHARS_STATE_CHANGE << 8) | 4),
242                 (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.END_ELEM << 8) | 0), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 2), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 2), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129),
243                 (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 5), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3),
244                 (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 4), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.END_NAME << 8) | 6), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.END_NAME << 8) | 7), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.END_NAME << 8) | 8), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129),
245                 (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 0), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 3),
246                 (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 0), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ERROR << 8) | 129),
247                 (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.FLUSH_CHARS_STATE_CHANGE << 8) | 1), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.PROC_CHAR_REF << 8) | 10), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 7), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10),
248                 (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 9), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.START_ELEM << 8) | 6), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.START_ELEM << 8) | 7), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 8), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129),
249                 (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 9), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.SET_ATTR_NAME << 8) | 11), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 12), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 130),
250                 (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 13), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.PROC_CHAR_REF << 8) | 10), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 10),
251                 (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 11), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 132), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ERROR << 8) | 132), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 132), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ERROR << 8) | 132), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ERROR << 8) | 132), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 132), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ERROR << 8) | 132), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 132), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 132), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ERROR << 8) | 132),
252                 (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.SET_ATTR_NAME << 8) | 11), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 12), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 130), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ERROR << 8) | 130),
253                 (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.SEND_CHARS << 8) | 2), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 16), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 134), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 134), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ERROR << 8) | 134), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ERROR << 8) | 134), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 134), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 134), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 134), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.ERROR << 8) | 134), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 134), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 134), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ERROR << 8) | 134),
254                 (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.SET_ATTR_VAL << 8) | 17), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.PROC_CHAR_REF << 8) | 14), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 14),
255                 (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.SET_ATTR_VAL << 8) | 17), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.PROC_CHAR_REF << 8) | 15), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 15),
256                 (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.START_CDATA << 8) | 18), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 0), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.START_CDATA << 8) | 19),
257                 (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.START_ELEM << 8) | 6), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.START_ELEM << 8) | 7), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.STATE_CHANGE << 8) | 17), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CHARS_STATE_CHANGE << 8) | 9), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ERROR << 8) | 129), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ERROR << 8) | 129),
258                 (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.END_CDATA << 8) | 10), (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 18),
259                 (ushort)(((ushort)CharKind.LEFT_BR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.SLASH << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.RIGHT_BR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.PI_MARK << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.EQ << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.AMP << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.SQUOTE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.BANG << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.LEFT_SQBR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.SPACE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.RIGHT_SQBR << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.DQUOTE << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19), (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.ACC_CDATA << 8) | 19),
260                 (ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.UNKNOWN << 8) | 255),
261                 0xFFFF
262         };
263
264         protected static string[] errors = {
265                 /* 0 */ "Expected element",
266                 /* 1 */ "Invalid character in tag",
267                 /* 2 */ "No '='",
268                 /* 3 */ "Invalid character entity",
269                 /* 4 */ "Invalid attr value",
270                 /* 5 */ "Empty tag",
271                 /* 6 */ "No end tag",
272                 /* 7 */ "Bad entity ref"
273         };
274
275         protected int line;
276         protected int col;
277         protected int[] twoCharBuff;
278         protected bool splitCData;
279
280         public MiniParser() {
281                 twoCharBuff = new int[2];
282                 splitCData = false;
283                 Reset();
284         }
285
286         public void Reset() {
287                 line = 0;
288                 col = 0;
289         }
290
291         protected static bool StrEquals(string str, StringBuilder sb, int sbStart, int len) {
292                 if (len != str.Length) return false;
293                 for (int i = 0; i < len; i++) {
294                         if (str[i] != sb[sbStart + i]) return false;
295                 }
296                 return true;
297         }
298
299         protected void FatalErr(string descr) {
300                 throw new XMLError(descr, this.line, this.col);
301         }
302
303         protected static int Xlat(int charCode, int state) {
304                 int p = state * INPUT_RANGE;
305                 int n = System.Math.Min(tbl.Length - p, INPUT_RANGE);
306                 for (;--n >= 0;) {
307                         ushort code = tbl[p];
308                         if (charCode == (code >> 12)) return (code & 0xFFF);
309                         p++;
310                 }
311                 return 0xFFF;
312         }
313
314         public void Parse(IReader reader, IHandler handler) {
315                 if (reader == null) throw new ArgumentNullException("reader");
316                 if (handler == null) handler = new HandlerAdapter();
317
318                 AttrListImpl attrList = new AttrListImpl();
319                 string lastAttrName = null;
320                 Stack tagStack = new Stack();
321                 string elementName = null;
322                 line = 1;
323                 col = 0;
324                 int currCh = 0;
325                 int stateCode = 0;
326                 StringBuilder sbChars = new StringBuilder();
327                 bool seenCData = false;
328                 bool isComment = false;
329                 bool isDTD = false;
330                 int bracketSwitch = 0;
331
332                 handler.OnStartParsing(this);
333
334                 while (true) {
335                         ++this.col;
336
337                         currCh = reader.Read();
338
339                         if (currCh == -1) {
340                                 if (stateCode != 0) {
341                                         FatalErr("Unexpected EOF");
342                                 }
343                                 break;
344                         }
345
346                         int charCode = "<>/?=&'\"![ ]\t\r\n".IndexOf((char)currCh) & 0xF;
347                         if (charCode == (int)CharKind.CR) continue; // ignore
348                         // whitepace ::= (#x20 | #x9 | #xd | #xa)+
349                         if (charCode == (int)CharKind.TAB) charCode = (int)CharKind.SPACE; // tab == space
350                         if (charCode == (int)CharKind.EOL) {
351                                 this.col = 0;
352                                 this.line++;
353                                 charCode = (int)CharKind.SPACE;
354                         }
355
356                         int actionCode = MiniParser.Xlat(charCode, stateCode);
357                         stateCode = actionCode & 0xFF;
358                         // Ignore newline inside attribute value.
359                         if (currCh == '\n' && (stateCode == 0xE || stateCode == 0xF)) continue;
360                         actionCode >>= 8;
361
362                         if (stateCode >= 0x80) {
363                                 if (stateCode == 0xFF) {
364                                         FatalErr("State dispatch error.");
365                                 } else {
366                                         FatalErr(errors[stateCode ^ 0x80]);
367                                 }
368                         }
369
370                         switch (actionCode) {
371                                 case (int)ActionCode.START_ELEM:
372                                         handler.OnStartElement(elementName, attrList);
373                                         if (currCh != '/') {
374                                                 tagStack.Push(elementName);
375                                         } else {
376                                                 handler.OnEndElement(elementName);
377                                         }
378                                         attrList.Clear();
379                                         break;
380
381                                 case (int)ActionCode.END_ELEM:
382                                         elementName = sbChars.ToString();
383                                         sbChars = new StringBuilder();
384                                         string endName = null;
385                                         if (tagStack.Count == 0 ||
386                                                 elementName != (endName = tagStack.Pop() as string)) {
387                                                 if (endName == null) {
388                                                         FatalErr("Tag stack underflow");
389                                                 } else {
390                                                         FatalErr(String.Format("Expected end tag '{0}' but found '{1}'", elementName, endName));
391                                                 }
392                                         }
393                                         handler.OnEndElement(elementName);
394                                         break;
395
396                                 case (int)ActionCode.END_NAME:
397                                         elementName = sbChars.ToString();
398                                         sbChars = new StringBuilder();
399                                         if (currCh != '/' && currCh != '>') break;
400                                         goto case (int)ActionCode.START_ELEM;
401
402                                 case (int)ActionCode.SET_ATTR_NAME:
403                                         lastAttrName = sbChars.ToString();
404                                         sbChars = new StringBuilder();
405                                         break;
406
407                                 case (int)ActionCode.SET_ATTR_VAL:
408                                         if (lastAttrName == null) FatalErr("Internal error.");
409                                         attrList.Add(lastAttrName, sbChars.ToString());
410                                         sbChars = new StringBuilder();
411                                         lastAttrName = null;
412                                         break;
413
414                                 case (int)ActionCode.SEND_CHARS:
415                                         handler.OnChars(sbChars.ToString());
416                                         sbChars = new StringBuilder();
417                                         break;
418
419                                 case (int)ActionCode.START_CDATA:
420                                         string cdata = "CDATA[";
421                                         isComment = false;
422                                         isDTD = false;
423
424                                         if (currCh == '-') {
425                                                 currCh = reader.Read();
426
427                                                 if (currCh != '-') FatalErr("Invalid comment");
428
429                                                 this.col++;
430                                                 isComment = true;
431                                                 twoCharBuff[0] = -1;
432                                                 twoCharBuff[1] = -1;
433                                         } else {
434                                                 if (currCh != '[') {
435                                                         isDTD = true;
436                                                         bracketSwitch = 0;
437                                                         break;
438                                                 }
439
440                                                 for (int i = 0; i < cdata.Length; i++) {
441                                                         if (reader.Read() != cdata[i]) {
442                                                                 this.col += i+1;
443                                                                 break;
444                                                         }
445                                                 }
446                                                 this.col += cdata.Length;
447                                                 seenCData = true;
448                                         }
449                                         break;
450
451                                 case (int)ActionCode.END_CDATA:
452                                         int n = 0;
453                                         currCh = ']';
454
455                                         while (currCh == ']') {
456                                                 currCh = reader.Read();
457                                                 n++;
458                                         }
459
460                                         if (currCh != '>') {
461                                                 for (int i = 0; i < n; i++) sbChars.Append(']');
462                                                 sbChars.Append((char)currCh);
463                                                 stateCode = 0x12;
464                                         } else {
465                                                 for (int i = 0; i < n-2; i++) sbChars.Append(']');
466                                                 seenCData = false;
467                                         }
468
469                                         this.col += n;
470                                         break;
471
472                                 case (int)ActionCode.ERROR:
473                                         FatalErr(String.Format("Error {0}", stateCode));
474                                         break;
475
476                                 case (int)ActionCode.STATE_CHANGE:
477                                         break;
478
479                                 case (int)ActionCode.FLUSH_CHARS_STATE_CHANGE:
480                                         sbChars = new StringBuilder();
481                                         if (currCh != '<') goto case (int)ActionCode.ACC_CHARS_STATE_CHANGE;
482                                         break;
483
484                                 case (int)ActionCode.ACC_CHARS_STATE_CHANGE:
485                                         sbChars.Append((char)currCh);
486                                         break;
487
488                                 case (int)ActionCode.ACC_CDATA:
489                                         if (isComment) {
490                                                 if (currCh == '>'
491                                                         && twoCharBuff[0] == '-'
492                                                         && twoCharBuff[1] == '-') {
493                                                         isComment = false;
494                                                         stateCode = 0;
495                                                 } else {
496                                                         twoCharBuff[0] = twoCharBuff[1];
497                                                         twoCharBuff[1] = currCh;
498                                                 }
499                                         } else if (isDTD) {
500                                                 if (currCh == '<' || currCh == '>') bracketSwitch ^= 1;
501                                                 if (currCh == '>' && bracketSwitch != 0) {
502                                                         isDTD = false;
503                                                         stateCode = 0;
504                                                 }
505                                         } else {
506                                                 if (this.splitCData
507                                                         && sbChars.Length > 0
508                                                         && seenCData) {
509                                                         handler.OnChars(sbChars.ToString());
510                                                         sbChars = new StringBuilder();
511                                                 }
512                                                 seenCData = false;
513                                                 sbChars.Append((char)currCh);
514                                         }
515                                         break;
516
517                                 case (int)ActionCode.PROC_CHAR_REF:
518                                         currCh = reader.Read();
519                                         int cl = this.col + 1;
520                                         if (currCh == '#') {    // character reference
521                                                 int r = 10;
522                                                 int chCode = 0;
523                                                 int nDigits = 0;
524                                                 currCh = reader.Read();
525                                                 cl++;
526
527                                                 if (currCh == 'x') {
528                                                         currCh = reader.Read();
529                                                         cl++;
530                                                         r=16;
531                                                 }
532
533                                                 NumberStyles style = r == 16 ? NumberStyles.HexNumber : NumberStyles.Integer;
534
535                                                 while (true) {
536                                                         int x = -1;
537                                                         if (Char.IsNumber((char)currCh) || "abcdef".IndexOf(Char.ToLower((char)currCh)) != -1) {
538                                                                 try {
539                                                                         x = Int32.Parse(new string((char)currCh, 1), style);
540                                                                 } catch (FormatException) {x = -1;}
541                                                         }
542                                                         if (x == -1) break;
543                                                         chCode *= r;
544                                                         chCode += x;
545                                                         nDigits++;
546                                                         currCh = reader.Read();
547                                                         cl++;
548                                                 }
549
550                                                 if (currCh == ';' && nDigits > 0) {
551                                                         sbChars.Append((char)chCode);
552                                                 } else {
553                                                         FatalErr("Bad char ref");
554                                                 }
555                                         } else {
556                                                 // entity reference
557                                                 string entityRefChars = "aglmopqstu"; // amp | apos | quot | gt | lt
558                                                 string entities = "&'\"><";
559
560                                                 int pos = 0;
561                                                 int entIdx = 0xF;
562                                                 int predShift = 0;
563
564                                                 int sbLen = sbChars.Length;
565
566                                                 while (true) {
567                                                         if (pos != 0xF) pos = entityRefChars.IndexOf((char)currCh) & 0xF;
568                                                         if (pos == 0xF) FatalErr(errors[7]);
569                                                         sbChars.Append((char)currCh);
570
571                                                         int path = "\uFF35\u3F8F\u4F8F\u0F5F\uFF78\uE1F4\u2299\uEEFF\uEEFF\uFF4F"[pos];
572                                                         int lBr = (path >> 4) & 0xF;
573                                                         int rBr = path & 0xF;
574                                                         int lPred = path >> 12;
575                                                         int rPred = (path >> 8) & 0xF;
576                                                         currCh = reader.Read();
577                                                         cl++;
578                                                         pos = 0xF;
579                                                         if (lBr != 0xF && currCh == entityRefChars[lBr]) {
580                                                                 if (lPred < 0xE) entIdx = lPred;
581 //                                                              pred = lPred;
582                                                                 predShift = 12; // left
583                                                         } else if (rBr != 0xF && currCh == entityRefChars[rBr]) {
584                                                                 if (rPred < 0xE) entIdx = rPred;
585 //                                                              pred = rPred;
586                                                                 predShift = 8; // right
587                                                         } else if (currCh == ';') {
588                                                                 if (entIdx != 0xF
589                                                                         && predShift != 0
590                                                                         && ((path >> predShift) & 0xF) == 0xE) break;
591                                                                 continue; // pos == 0xF
592                                                         }
593
594                                                         pos=0;
595
596                                                 }
597
598                                                 int l = cl - this.col - 1;
599
600                                                 if ((l > 0 && l < 5)
601                                                         &&(StrEquals("amp", sbChars, sbLen, l)
602                                                         || StrEquals("apos", sbChars, sbLen, l)
603                                                         || StrEquals("quot", sbChars, sbLen, l)
604                                                         || StrEquals("lt", sbChars, sbLen, l)
605                                                         || StrEquals("gt", sbChars, sbLen, l))
606                                                         ) {
607                                                                 sbChars.Length = sbLen;
608                                                                 sbChars.Append(entities[entIdx]);
609                                                 } else FatalErr(errors[7]);
610                                         }
611
612                                         this.col = cl;
613                                         break;
614
615                                 default:
616                                         FatalErr(String.Format("Unexpected action code - {0}.", actionCode));
617                                         break;
618                         }
619                 } // while (true)
620
621                 handler.OnEndParsing(this);
622
623         } // Parse
624
625 }
626
627 }