Dont make function call to StringBuffer
[mono.git] / mcs / class / System.XML / System.Xml / XmlParserInput.cs
1 //
2 // System.Xml.XmlParserInput
3 //
4 // Author:
5 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
6 //
7 //      (C)2003 Atsushi Enomoto
8 //
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
41                 // specified character.
42                 public void Close ()
43                 {
44                         this.reader.Close ();
45                 }
46
47                 public void Expect (int expected)
48                 {
49                         int ch = ReadChar ();
50
51                         if (ch != expected) {
52                                 throw ReaderError (
53                                         String.Format (
54                                                 "expected '{0}' ({1:X}) but found '{2}' ({3:X})",
55                                                 (char)expected,
56                                                 expected,
57                                                 (char)ch,
58                                                 ch));
59                         }
60                 }
61
62                 public void Expect (string expected)
63                 {
64                         int len = expected.Length;
65                         for(int i=0; i< len; i++)
66                                 Expect (expected[i]);
67                 }
68
69                 public void InsertParameterEntityBuffer (string value)
70                 {
71                         this.peBuffer.Insert (0, ' ' + value + ' ');
72                         peStored = true;
73                 }
74
75                 public int PeekChar ()
76                 {
77                         if (peStored)
78                                 return peBuffer [0];
79
80                         if (can_seek)
81                                 return reader.Peek ();
82
83                         if (has_peek)
84                                 return peek_char;
85
86                         peek_char = reader.Read ();
87                         has_peek = true;
88                         return peek_char;
89                 }
90
91                 public int ReadChar ()
92                 {
93                         int ch;
94
95                         if (peStored) {
96                                 ch = peBuffer [0];
97                                 peBuffer.Remove (0, 1);
98                                 peStored = peBuffer.Length > 0;
99                                 // I decided not to add character to currentTag with respect to PERef value
100                                 return ch;
101                         }
102
103                         if (has_peek) {
104                                 ch = peek_char;
105                                 has_peek = false;
106                         } else {
107                                 ch = reader.Read ();
108                         }
109
110                         if (ch == '\n') {
111                                 line++;
112                                 column = 1;
113                         } else {
114                                 column++;
115                         }
116                         currentMarkup.Append ((char) ch);
117                         return ch;
118                 }
119                 #endregion
120
121                 #region Public Properties
122                 public string BaseURI {
123                         get { return baseURI; }
124                 }
125
126                 public StringBuilder CurrentMarkup {
127                         get { return this.currentMarkup; }
128                 }
129
130                 private char [] wsChars = new char [] {' ', '\r', '\n', '\t'};
131                 public bool HasPEBuffer {
132                         get {
133                                 if (!peStored)
134                                         return false;
135                                 else if (peBuffer.ToString ().Trim (wsChars).Length == 0)
136                                         return false;
137                                 else
138                                         return true;
139                         }
140                 }
141
142                 public int LineNumber {
143                         get { return line; }
144                 }
145
146                 public int LinePosition {
147                         get { return column; }
148                 }
149                 public string Name \r
150                 {
151                         get {
152                                 return currentMarkup.ToString (parsedNameStart, parsedNameEnd - parsedNameStart);
153                         }
154                 }
155
156                 public string Value {
157                         get {
158                                 return currentMarkup.ToString (parsedValueStart, parsedValueEnd - parsedValueStart);
159                         }
160                 }
161                 #endregion
162 \r
163                 #region Privates\r
164                 private void ReadNameOrNmToken(bool isNameToken)\r
165                 {\r
166                         parsedNameStart = currentMarkup.Length;\r
167                         if(isNameToken) {\r
168                                 if (!XmlChar.IsNameChar (PeekChar ()))\r
169                                         throw ReaderError ("a name did not start with a legal character " + PeekChar ());\r
170                         }\r
171                         else {\r
172                                 if (!XmlChar.IsFirstNameChar (PeekChar ()))\r
173                                         throw ReaderError ("a name did not start with a valid character " + PeekChar () + "(" + (char) PeekChar () + ")");\r
174                         }\r
175
176                         ReadChar ();
177
178                         while (XmlChar.IsNameChar (PeekChar ())) {
179                                 ReadChar ();
180                         }
181
182                         parsedNameEnd = currentMarkup.Length;
183                 }
184
185                 // Privates
186                 TextReader reader;\r
187                 bool can_seek;
188                 bool has_peek;
189                 int peek_char;
190                 int line;
191                 int column;
192                 StringBuilder currentMarkup = new StringBuilder ();
193                 int parsedNameStart;
194                 int parsedNameEnd;
195                 int parsedValueStart;
196                 int parsedValueEnd;
197                 StringBuilder peBuffer = new StringBuilder ();
198                 string baseURI;
199                 bool peStored = false;
200
201                 private int ParseCharReference (string name)
202                 {
203                         int ret = -1;
204                         if (name.Length > 0 && name [0] == '#') {
205                                 if (name [1] == 'x')
206                                         ret = int.Parse (name.Substring (2, name.Length - 2), NumberStyles.None & NumberStyles.AllowHexSpecifier);
207                                 else
208                                         ret = int.Parse (name.Substring (1, name.Length - 1));
209                         }
210                         return ret;
211                 }
212
213                 private int ParseKnownEntityReference (string name)
214                 {
215                         switch (name) {
216                         case "quot": return '"';
217                         case "lt": return '<';
218                         case "gt": return '>';
219                         case "amp": return '&';
220                         case "apos": return '\'';
221                         }
222                         return -1;
223                 }
224
225                 private XmlException ReaderError (string message)
226                 {
227                         return new XmlException (message, line, column);
228                 }
229                 #endregion\r
230         }\r
231 }\r