MiniParser.cs 37 KB

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