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