Fix a big in Close () method - close the underlying stream.
[mono.git] / mcs / class / System.XML / System.Xml / XmlParserInput.cs
1 //\r
2 // System.Xml.XmlParserInput\r
3 //\r
4 // Author:\r
5 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)\r
6 //\r
7 //      (C)2003 Atsushi Enomoto\r
8 //\r
9 using System;\r
10 using System.IO;\r
11 using System.Text;\r
12 using System.Xml;\r
13 using System.Globalization;\r
14 \r
15 namespace Mono.Xml.Native\r
16 {\r
17         public class XmlParserInput\r
18         {\r
19                 #region ctor\r
20                 public XmlParserInput (TextReader reader, string baseURI)\r
21                         : this (reader, baseURI, 1, 1)\r
22                 {\r
23                 }\r
24 \r
25                 public XmlParserInput (TextReader reader, string baseURI, int line, int column)\r
26                 {\r
27                         this.reader = reader;\r
28 \r
29                         StreamReader sr = reader as StreamReader;\r
30                         if (sr != null)\r
31                                 can_seek = sr.BaseStream.CanSeek;\r
32 \r
33                         this.line = line;\r
34                         this.column = column;\r
35                         this.baseURI = baseURI;\r
36                 }\r
37                 #endregion\r
38 \r
39                 #region Public Methods\r
40                 // Read the next character and compare it against the\r
41                 // specified character.\r
42                 public void Close ()\r
43                 {\r
44                         this.reader.Close ();\r
45                 }\r
46 \r
47                 public void Expect (int expected)\r
48                 {\r
49                         int ch = ReadChar ();\r
50 \r
51                         if (ch != expected) {\r
52                                 throw ReaderError (\r
53                                         String.Format (\r
54                                                 "expected '{0}' ({1:X}) but found '{2}' ({3:X})",\r
55                                                 (char)expected,\r
56                                                 expected,\r
57                                                 (char)ch,\r
58                                                 ch));\r
59                         }\r
60                 }\r
61 \r
62                 public void Expect (string expected)\r
63                 {\r
64                         int len = expected.Length;\r
65                         for(int i=0; i< len; i++)\r
66                                 Expect (expected[i]);\r
67                 }\r
68 \r
69                 public void InsertParameterEntityBuffer (string value)\r
70                 {\r
71                         this.peBuffer.Insert (0, ' ' + value + ' ');\r
72                         peStored = true;\r
73                 }\r
74 \r
75                 public int PeekChar ()\r
76                 {\r
77                         if (peStored)\r
78                                 return peBuffer [0];\r
79 \r
80                         if (can_seek)\r
81                                 return reader.Peek ();\r
82 \r
83                         if (has_peek)\r
84                                 return peek_char;\r
85 \r
86                         peek_char = reader.Read ();\r
87                         has_peek = true;\r
88                         return peek_char;\r
89                 }\r
90 \r
91                 public int ReadChar ()\r
92                 {\r
93                         int ch;\r
94 \r
95                         if (peStored) {\r
96                                 ch = peBuffer [0];\r
97                                 peBuffer.Remove (0, 1);\r
98                                 peStored = peBuffer.Length > 0;\r
99                                 // I decided not to add character to currentTag with respect to PERef value\r
100                                 return ch;\r
101                         }\r
102 \r
103                         if (has_peek) {\r
104                                 ch = peek_char;\r
105                                 has_peek = false;\r
106                         } else {\r
107                                 ch = reader.Read ();\r
108                         }\r
109 \r
110                         if (ch == '\n') {\r
111                                 line++;\r
112                                 column = 1;\r
113                         } else {\r
114                                 column++;\r
115                         }\r
116                         currentMarkup.Append ((char) ch);\r
117                         return ch;\r
118                 }\r
119                 #endregion\r
120 \r
121                 #region Public Properties\r
122                 public string BaseURI {\r
123                         get { return baseURI; }\r
124                 }\r
125 \r
126                 public StringBuilder CurrentMarkup {\r
127                         get { return this.currentMarkup; }\r
128                 }\r
129 \r
130                 public bool HasPEBuffer {\r
131                         get {\r
132                                 if (!peStored)\r
133                                         return false;\r
134                                 else if (peBuffer.ToString ().Trim (XmlChar.WhitespaceChars).Length == 0)\r
135                                         return false;\r
136                                 else\r
137                                         return true;\r
138                         }\r
139                 }\r
140 \r
141                 public int LineNumber {\r
142                         get { return line; }\r
143                 }\r
144 \r
145                 public int LinePosition {\r
146                         get { return column; }\r
147                 }\r
148 \r
149                 public bool InitialState {\r
150                         get { return initialState; }\r
151                         set { initialState = value; }\r
152                 }\r
153 \r
154                 #endregion\r
155 \r
156                 #region Privates\r
157                 TextReader reader;\r
158                 bool can_seek;\r
159                 bool has_peek;\r
160                 int peek_char;\r
161                 int line;\r
162                 int column;\r
163                 StringBuilder currentMarkup = new StringBuilder ();\r
164                 StringBuilder peBuffer = new StringBuilder ();\r
165                 string baseURI;\r
166                 bool peStored = false;\r
167                 bool initialState = true;\r
168 \r
169                 private int ParseCharReference (string name)\r
170                 {\r
171                         int ret = -1;\r
172                         if (name.Length > 0 && name [0] == '#') {\r
173                                 if (name [1] == 'x')\r
174                                         ret = int.Parse (name.Substring (2, name.Length - 2), NumberStyles.None & NumberStyles.AllowHexSpecifier);\r
175                                 else\r
176                                         ret = int.Parse (name.Substring (1, name.Length - 1));\r
177                         }\r
178                         return ret;\r
179                 }\r
180 \r
181                 private int ParseKnownEntityReference (string name)\r
182                 {\r
183                         switch (name) {\r
184                         case "quot": return '"';\r
185                         case "lt": return '<';\r
186                         case "gt": return '>';\r
187                         case "amp": return '&';\r
188                         case "apos": return '\'';\r
189                         }\r
190                         return -1;\r
191                 }\r
192 \r
193                 private XmlException ReaderError (string message)\r
194                 {\r
195                         return new XmlException (message, null, line, column);\r
196                 }\r
197                 #endregion\r
198         }\r
199 }\r