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