2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / Mono.Xml.Ext / Mono.Xml / XmlChar.cs
1
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
10 // 
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 // 
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 using System;\r
23 \r
24 namespace System.Xml\r
25 {\r
26         /// <summary>\r
27         /// http://www.w3.org/TR/REC-xml\r
28         /// </summary>\r
29         /// <remarks>\r
30         /// Includes code and Ideas from  org.apache.xerces.util.XMLChar class of Xerces 2.0.1\r
31         /// However, No surrogate support is included in this class.\r
32         /// This class is currently public. Make it internal after testing completes\r
33         /// </remarks>\r
34         internal class XmlChar//XmlConstructs\r
35         {\r
36                 internal static readonly char [] WhitespaceChars = {' ', '\n', '\t', '\r'};
37 \r
38                 /** Character flags. */\r
39                 internal static readonly byte [] CHARS = new byte [1 << 16];\r
40 \r
41                 /** Valid character mask. */\r
42                 internal const int VALID = 0x01;\r
43 \r
44                 /** Space character mask. */\r
45                 internal const int SPACE = 0x02;\r
46 \r
47                 /** Name start character mask. */\r
48                 internal const int NAME_START = 0x04;\r
49 \r
50                 /** Name character mask. */\r
51                 internal const int NAME = 0x08;\r
52 \r
53                 /** Pubid character mask. */\r
54                 internal const int PUBID = 0x10;\r
55                 /** \r
56                          * Content character mask. Special characters are those that can\r
57                          * be considered the start of markup, such as '&lt;' and '&amp;'. \r
58                          * The various newline characters are considered special as well.\r
59                          * All other valid XML characters can be considered content.\r
60                          * <p>\r
61                          * This is an optimization for the inner loop of character scanning.\r
62                          */\r
63                 internal const int CONTENT = 0x20;\r
64 \r
65                 /** NCName start character mask. */\r
66                 internal const int NCNAME_START = 0x40;\r
67 \r
68                 /** NCName character mask. */\r
69                 internal const int NCNAME = 0x80;\r
70         \r
71                 static XmlChar()\r
72                 {\r
73                         //\r
74                         // [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] |\r
75                         //              [#xE000-#xFFFD] | [#x10000-#x10FFFF]\r
76                         //\r
77                         int[] charRange = { \r
78                                                                   0x0009, 0x000A, 0x000D, 0x000D, 0x0020, 0xD7FF, 0xE000, 0xFFFD,\r
79                         };\r
80 \r
81                         //\r
82                         // [3] S ::= (#x20 | #x9 | #xD | #xA)+\r
83                         //\r
84                         int[] spaceChar = { \r
85                                                                   0x0020, 0x0009, 0x000D, 0x000A,\r
86                         };\r
87 \r
88                         //\r
89                         // [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |\r
90                         //                  CombiningChar | Extender\r
91                         //\r
92                         int[] nameChar = { \r
93                                                                  0x002D, 0x002E, // '-' and '.'\r
94                         };\r
95 \r
96                         //\r
97                         // [5] Name ::= (Letter | '_' | ':') (NameChar)*\r
98                         //\r
99 \r
100                         int[] nameStartChar = { \r
101                                                                           0x003A, 0x005F, // ':' and '_'\r
102                         };\r
103 \r
104                         //\r
105                         // [13] PubidChar ::= #x20 | 0xD | 0xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]\r
106                         //\r
107 \r
108                         int[] pubidChar = {\r
109                                                                   0x000A, 0x000D, 0x0020, 0x0021, 0x0023, 0x0024, 0x0025, 0x003D,\r
110                                                                   0x005F\r
111                                                           };\r
112 \r
113                         int[] pubidRange = {\r
114                                                                    0x0027, 0x003B, 0x003F, 0x005A, 0x0061, 0x007A\r
115                                                            };\r
116 \r
117                         //\r
118                         // [84] Letter ::= BaseChar | Ideographic\r
119                         //\r
120 \r
121                         int[] letterRange = {\r
122                                                                         // BaseChar\r
123                                                                         0x0041, 0x005A, 0x0061, 0x007A, 0x00C0, 0x00D6, 0x00D8, 0x00F6,\r
124                                                                         0x00F8, 0x0131, 0x0134, 0x013E, 0x0141, 0x0148, 0x014A, 0x017E,\r
125                                                                         0x0180, 0x01C3, 0x01CD, 0x01F0, 0x01F4, 0x01F5, 0x01FA, 0x0217,\r
126                                                                         0x0250, 0x02A8, 0x02BB, 0x02C1, 0x0388, 0x038A, 0x038E, 0x03A1,\r
127                                                                         0x03A3, 0x03CE, 0x03D0, 0x03D6, 0x03E2, 0x03F3, 0x0401, 0x040C,\r
128                                                                         0x040E, 0x044F, 0x0451, 0x045C, 0x045E, 0x0481, 0x0490, 0x04C4,\r
129                                                                         0x04C7, 0x04C8, 0x04CB, 0x04CC, 0x04D0, 0x04EB, 0x04EE, 0x04F5,\r
130                                                                         0x04F8, 0x04F9, 0x0531, 0x0556, 0x0561, 0x0586, 0x05D0, 0x05EA,\r
131                                                                         0x05F0, 0x05F2, 0x0621, 0x063A, 0x0641, 0x064A, 0x0671, 0x06B7,\r
132                                                                         0x06BA, 0x06BE, 0x06C0, 0x06CE, 0x06D0, 0x06D3, 0x06E5, 0x06E6,\r
133                                                                         0x0905, 0x0939, 0x0958, 0x0961, 0x0985, 0x098C, 0x098F, 0x0990,\r
134                                                                         0x0993, 0x09A8, 0x09AA, 0x09B0, 0x09B6, 0x09B9, 0x09DC, 0x09DD,\r
135                                                                         0x09DF, 0x09E1, 0x09F0, 0x09F1, 0x0A05, 0x0A0A, 0x0A0F, 0x0A10,\r
136                                                                         0x0A13, 0x0A28, 0x0A2A, 0x0A30, 0x0A32, 0x0A33, 0x0A35, 0x0A36,\r
137                                                                         0x0A38, 0x0A39, 0x0A59, 0x0A5C, 0x0A72, 0x0A74, 0x0A85, 0x0A8B,\r
138                                                                         0x0A8F, 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3,\r
139                                                                         0x0AB5, 0x0AB9, 0x0B05, 0x0B0C, 0x0B0F, 0x0B10, 0x0B13, 0x0B28,\r
140                                                                         0x0B2A, 0x0B30, 0x0B32, 0x0B33, 0x0B36, 0x0B39, 0x0B5C, 0x0B5D,\r
141                                                                         0x0B5F, 0x0B61, 0x0B85, 0x0B8A, 0x0B8E, 0x0B90, 0x0B92, 0x0B95,\r
142                                                                         0x0B99, 0x0B9A, 0x0B9E, 0x0B9F, 0x0BA3, 0x0BA4, 0x0BA8, 0x0BAA,\r
143                                                                         0x0BAE, 0x0BB5, 0x0BB7, 0x0BB9, 0x0C05, 0x0C0C, 0x0C0E, 0x0C10,\r
144                                                                         0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C60, 0x0C61,\r
145                                                                         0x0C85, 0x0C8C, 0x0C8E, 0x0C90, 0x0C92, 0x0CA8, 0x0CAA, 0x0CB3,\r
146                                                                         0x0CB5, 0x0CB9, 0x0CE0, 0x0CE1, 0x0D05, 0x0D0C, 0x0D0E, 0x0D10,\r
147                                                                         0x0D12, 0x0D28, 0x0D2A, 0x0D39, 0x0D60, 0x0D61, 0x0E01, 0x0E2E,\r
148                                                                         0x0E32, 0x0E33, 0x0E40, 0x0E45, 0x0E81, 0x0E82, 0x0E87, 0x0E88,\r
149                                                                         0x0E94, 0x0E97, 0x0E99, 0x0E9F, 0x0EA1, 0x0EA3, 0x0EAA, 0x0EAB,\r
150                                                                         0x0EAD, 0x0EAE, 0x0EB2, 0x0EB3, 0x0EC0, 0x0EC4, 0x0F40, 0x0F47,\r
151                                                                         0x0F49, 0x0F69, 0x10A0, 0x10C5, 0x10D0, 0x10F6, 0x1102, 0x1103,\r
152                                                                         0x1105, 0x1107, 0x110B, 0x110C, 0x110E, 0x1112, 0x1154, 0x1155,\r
153                                                                         0x115F, 0x1161, 0x116D, 0x116E, 0x1172, 0x1173, 0x11AE, 0x11AF,\r
154                                                                         0x11B7, 0x11B8, 0x11BC, 0x11C2, 0x1E00, 0x1E9B, 0x1EA0, 0x1EF9,\r
155                                                                         0x1F00, 0x1F15, 0x1F18, 0x1F1D, 0x1F20, 0x1F45, 0x1F48, 0x1F4D,\r
156                                                                         0x1F50, 0x1F57, 0x1F5F, 0x1F7D, 0x1F80, 0x1FB4, 0x1FB6, 0x1FBC,\r
157                                                                         0x1FC2, 0x1FC4, 0x1FC6, 0x1FCC, 0x1FD0, 0x1FD3, 0x1FD6, 0x1FDB,\r
158                                                                         0x1FE0, 0x1FEC, 0x1FF2, 0x1FF4, 0x1FF6, 0x1FFC, 0x212A, 0x212B,\r
159                                                                         0x2180, 0x2182, 0x3041, 0x3094, 0x30A1, 0x30FA, 0x3105, 0x312C,\r
160                                                                         0xAC00, 0xD7A3,\r
161                                                                         // Ideographic\r
162                                                                         0x3021, 0x3029, 0x4E00, 0x9FA5,\r
163                         };\r
164                         int[] letterChar = {\r
165                                                                    // BaseChar\r
166                                                                    0x0386, 0x038C, 0x03DA, 0x03DC, 0x03DE, 0x03E0, 0x0559, 0x06D5,\r
167                                                                    0x093D, 0x09B2, 0x0A5E, 0x0A8D, 0x0ABD, 0x0AE0, 0x0B3D, 0x0B9C,\r
168                                                                    0x0CDE, 0x0E30, 0x0E84, 0x0E8A, 0x0E8D, 0x0EA5, 0x0EA7, 0x0EB0,\r
169                                                                    0x0EBD, 0x1100, 0x1109, 0x113C, 0x113E, 0x1140, 0x114C, 0x114E,\r
170                                                                    0x1150, 0x1159, 0x1163, 0x1165, 0x1167, 0x1169, 0x1175, 0x119E,\r
171                                                                    0x11A8, 0x11AB, 0x11BA, 0x11EB, 0x11F0, 0x11F9, 0x1F59, 0x1F5B,\r
172                                                                    0x1F5D, 0x1FBE, 0x2126, 0x212E,\r
173                                                                    // Ideographic\r
174                                                                    0x3007,\r
175                         };\r
176 \r
177                         //\r
178                         // [87] CombiningChar ::= ...\r
179                         //\r
180 \r
181                         int[] combiningCharRange = {\r
182                                                                                    0x0300, 0x0345, 0x0360, 0x0361, 0x0483, 0x0486, 0x0591, 0x05A1,\r
183                                                                                    0x05A3, 0x05B9, 0x05BB, 0x05BD, 0x05C1, 0x05C2, 0x064B, 0x0652,\r
184                                                                                    0x06D6, 0x06DC, 0x06DD, 0x06DF, 0x06E0, 0x06E4, 0x06E7, 0x06E8,\r
185                                                                                    0x06EA, 0x06ED, 0x0901, 0x0903, 0x093E, 0x094C, 0x0951, 0x0954,\r
186                                                                                    0x0962, 0x0963, 0x0981, 0x0983, 0x09C0, 0x09C4, 0x09C7, 0x09C8,\r
187                                                                                    0x09CB, 0x09CD, 0x09E2, 0x09E3, 0x0A40, 0x0A42, 0x0A47, 0x0A48,\r
188                                                                                    0x0A4B, 0x0A4D, 0x0A70, 0x0A71, 0x0A81, 0x0A83, 0x0ABE, 0x0AC5,\r
189                                                                                    0x0AC7, 0x0AC9, 0x0ACB, 0x0ACD, 0x0B01, 0x0B03, 0x0B3E, 0x0B43,\r
190                                                                                    0x0B47, 0x0B48, 0x0B4B, 0x0B4D, 0x0B56, 0x0B57, 0x0B82, 0x0B83,\r
191                                                                                    0x0BBE, 0x0BC2, 0x0BC6, 0x0BC8, 0x0BCA, 0x0BCD, 0x0C01, 0x0C03,\r
192                                                                                    0x0C3E, 0x0C44, 0x0C46, 0x0C48, 0x0C4A, 0x0C4D, 0x0C55, 0x0C56,\r
193                                                                                    0x0C82, 0x0C83, 0x0CBE, 0x0CC4, 0x0CC6, 0x0CC8, 0x0CCA, 0x0CCD,\r
194                                                                                    0x0CD5, 0x0CD6, 0x0D02, 0x0D03, 0x0D3E, 0x0D43, 0x0D46, 0x0D48,\r
195                                                                                    0x0D4A, 0x0D4D, 0x0E34, 0x0E3A, 0x0E47, 0x0E4E, 0x0EB4, 0x0EB9,\r
196                                                                                    0x0EBB, 0x0EBC, 0x0EC8, 0x0ECD, 0x0F18, 0x0F19, 0x0F71, 0x0F84,\r
197                                                                                    0x0F86, 0x0F8B, 0x0F90, 0x0F95, 0x0F99, 0x0FAD, 0x0FB1, 0x0FB7,\r
198                                                                                    0x20D0, 0x20DC, 0x302A, 0x302F,\r
199                         };\r
200 \r
201                         int[] combiningCharChar = {\r
202                                                                                   0x05BF, 0x05C4, 0x0670, 0x093C, 0x094D, 0x09BC, 0x09BE, 0x09BF,\r
203                                                                                   0x09D7, 0x0A02, 0x0A3C, 0x0A3E, 0x0A3F, 0x0ABC, 0x0B3C, 0x0BD7,\r
204                                                                                   0x0D57, 0x0E31, 0x0EB1, 0x0F35, 0x0F37, 0x0F39, 0x0F3E, 0x0F3F,\r
205                                                                                   0x0F97, 0x0FB9, 0x20E1, 0x3099, 0x309A,\r
206                         };\r
207 \r
208                         //\r
209                         // [88] Digit ::= ...\r
210                         //\r
211 \r
212                         int[] digitRange = {\r
213                                                                    0x0030, 0x0039, 0x0660, 0x0669, 0x06F0, 0x06F9, 0x0966, 0x096F,\r
214                                                                    0x09E6, 0x09EF, 0x0A66, 0x0A6F, 0x0AE6, 0x0AEF, 0x0B66, 0x0B6F,\r
215                                                                    0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF, 0x0D66, 0x0D6F,\r
216                                                                    0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F29,\r
217                         };\r
218 \r
219                         //\r
220                         // [89] Extender ::= ...\r
221                         //\r
222 \r
223                         int[] extenderRange = {\r
224                                                                           0x3031, 0x3035, 0x309D, 0x309E, 0x30FC, 0x30FE,\r
225                         };\r
226 \r
227                         int[] extenderChar = {\r
228                                                                          0x00B7, 0x02D0, 0x02D1, 0x0387, 0x0640, 0x0E46, 0x0EC6, 0x3005,\r
229                         };\r
230 \r
231                         //\r
232                         // SpecialChar ::= '<', '&', '\n', '\r', ']'\r
233                         //\r
234 \r
235                         int[] specialChar = {\r
236                                                                         '<', '&', '\n', '\r', ']',\r
237                         };\r
238 \r
239                         //\r
240                         // Initialize\r
241                         //\r
242 \r
243                         // set valid characters\r
244                         for (int i = 0; i < charRange.Length; i += 2) \r
245                         {\r
246                                 for (int j = charRange[i]; j <= charRange[i + 1]; j++) \r
247                                 {\r
248                                         CHARS[j] = (byte)(CHARS[j] | VALID | CONTENT);\r
249                                 }\r
250                         }\r
251 \r
252                         // remove special characters\r
253                         for (int i = 0; i < specialChar.Length; i++) \r
254                         {\r
255                                 CHARS[specialChar[i]] = (byte)(CHARS[specialChar[i]] & ~CONTENT);\r
256                         }\r
257 \r
258                         // set space characters\r
259                         for (int i = 0; i < spaceChar.Length; i++) \r
260                         {\r
261                                 CHARS[spaceChar[i]] = (byte)(CHARS[spaceChar[i]] | SPACE);\r
262                         }\r
263 \r
264                         // set name start characters\r
265                         for (int i = 0; i < nameStartChar.Length; i++) \r
266                         {\r
267                                 CHARS[nameStartChar[i]] = (byte)(CHARS[nameStartChar[i]] | NAME_START | NAME | \r
268                                         NCNAME_START | NCNAME);\r
269                         }\r
270                         for (int i = 0; i < letterRange.Length; i += 2) \r
271                         {\r
272                                 for (int j = letterRange[i]; j <= letterRange[i + 1]; j++) \r
273                                 {\r
274                                         CHARS[j] = (byte)(CHARS[j] | NAME_START | NAME |        NCNAME_START | NCNAME);\r
275                                 }\r
276                         }\r
277                         for (int i = 0; i < letterChar.Length; i++) \r
278                         {\r
279                                 CHARS[letterChar[i]] = (byte)(CHARS[letterChar[i]] | NAME_START | NAME |\r
280                                         NCNAME_START | NCNAME);\r
281                         }\r
282 \r
283                         // set name characters\r
284                         for (int i = 0; i < nameChar.Length; i++) \r
285                         {\r
286                                 CHARS[nameChar[i]] = (byte)(CHARS[nameChar[i]] | NAME | NCNAME);\r
287                         }\r
288                         for (int i = 0; i < digitRange.Length; i += 2) \r
289                         {\r
290                                 for (int j = digitRange[i]; j <= digitRange[i + 1]; j++) \r
291                                 {\r
292                                         CHARS[j] = (byte)(CHARS[j] | NAME | NCNAME);\r
293                                 }\r
294                         }\r
295                         for (int i = 0; i < combiningCharRange.Length; i += 2) \r
296                         {\r
297                                 for (int j = combiningCharRange[i]; j <= combiningCharRange[i + 1]; j++) \r
298                                 {\r
299                                         CHARS[j] = (byte)(CHARS[j] | NAME | NCNAME);\r
300                                 }\r
301                         }\r
302                         for (int i = 0; i < combiningCharChar.Length; i++) \r
303                         {\r
304                                 CHARS[combiningCharChar[i]] = (byte)(CHARS[combiningCharChar[i]] | NAME | NCNAME);\r
305                         }\r
306                         for (int i = 0; i < extenderRange.Length; i += 2) \r
307                         {\r
308                                 for (int j = extenderRange[i]; j <= extenderRange[i + 1]; j++) \r
309                                 {\r
310                                         CHARS[j] = (byte)(CHARS[j] | NAME | NCNAME);\r
311                                 }\r
312                         }\r
313                         for (int i = 0; i < extenderChar.Length; i++) \r
314                         {\r
315                                 CHARS[extenderChar[i]] = (byte)(CHARS[extenderChar[i]] | NAME | NCNAME);\r
316                         }\r
317 \r
318                         // remove ':' from allowable NCNAME_START and NCNAME chars\r
319                         CHARS[':'] = (byte)(CHARS[':'] & ~(NCNAME_START | NCNAME));\r
320 \r
321                         // set Pubid characters\r
322                         for (int i = 0; i < pubidChar.Length; i++) \r
323                         {\r
324                                 CHARS[pubidChar[i]] = (byte)(CHARS[pubidChar[i]] | PUBID);\r
325                         }\r
326                         for (int i = 0; i < pubidRange.Length; i += 2) \r
327                         {\r
328                                 for (int j = pubidRange[i]; j <= pubidRange[i + 1]; j++) \r
329                                 {\r
330                                         CHARS[j] = (byte)(CHARS[j] | PUBID);\r
331                                 }\r
332                         }\r
333                 }\r
334 \r
335                 private XmlChar()\r
336                 {\r
337                 }\r
338 \r
339 \r
340                 //Static Methods\r
341 \r
342                 /// <summary>\r
343                 /// Returns true if the specified character is valid.\r
344                 /// </summary>\r
345                 /// <param name="c">The character to check.</param>\r
346                 public static bool IsValid(char c) \r
347                 {\r
348                         return c > 0 && ((CHARS[c] & VALID) != 0);\r
349                 }\r
350 \r
351                 public static bool IsValid (int c) \r
352                 {\r
353                         if (c > 0xffff)\r
354                                 return c < 0x110000;\r
355                         return c > 0 && ((CHARS[c] & VALID) != 0);\r
356                 }\r
357 \r
358                 /// <summary>\r
359                 /// Returns true if the specified character is invalid.\r
360                 /// </summary>\r
361                 /// <param name="c">The character to check.</param>\r
362                 public static bool IsInvalid(char c) \r
363                 {\r
364                         return !IsValid(c);\r
365                 }\r
366 \r
367                 public static bool IsInvalid(int c) \r
368                 {\r
369                         return !IsValid(c);\r
370                 }\r
371 \r
372                 /// <summary>\r
373                 /// Returns true if the specified character can be considered content.\r
374                 /// </summary>\r
375                 /// <param name="c">The character to check.</param>\r
376                 public static bool IsContent(char c) \r
377                 {\r
378                         return (CHARS[c] & CONTENT) != 0;\r
379                 }\r
380 \r
381                 public static bool IsContent(int c) \r
382                 {\r
383                         return c > 0 && c < CHARS.Length && (CHARS[c] & CONTENT) != 0;\r
384                 }\r
385 \r
386                 /// <summary>\r
387                 /// Returns true if the specified character can be considered markup.\r
388                 /// Markup characters include '&lt;', '&amp;', and '%'.\r
389                 /// </summary>\r
390                 /// <param name="c">The character to check.</param>\r
391                 public static bool IsMarkup(char c) \r
392                 {\r
393                         return c == '<' || c == '&' || c == '%';\r
394                 }\r
395 \r
396                 public static bool IsMarkup(int c) \r
397                 {\r
398                         return c > 0 && c < CHARS.Length && (c == '<' || c == '&' || c == '%');\r
399                 }\r
400 \r
401                 /// <summary>\r
402                 /// Returns true if the specified character is a space character\r
403                 /// as defined by production [3] in the XML 1.0 specification. \r
404                 /// </summary>\r
405                 /// <param name="c">The character to check.</param>\r
406                 /// <returns></returns>\r
407                 public static bool IsWhitespace (char c) \r
408                 {\r
409                         return (CHARS[c] & SPACE) != 0;\r
410                 }\r
411 \r
412                 public static bool IsWhitespace (int c) \r
413                 {\r
414                         return c > 0 && c < CHARS.Length && (CHARS[c] & SPACE) != 0;\r
415                 }\r
416 \r
417                 /// <summary>\r
418                 /// Returns true if the specified character is a valid name start\r
419                 /// character as defined by production [5] in the XML 1.0 specification.\r
420                 /// </summary>\r
421                 /// <param name="c">The character to check.</param>\r
422                 public static bool IsFirstNameChar (char c) \r
423                 {\r
424                         return (CHARS[c] & NAME_START) != 0;\r
425                 } \r
426 \r
427                 public static bool IsFirstNameChar (int c) \r
428                 {\r
429                         return c > 0 && c < CHARS.Length && (CHARS[c] & NAME_START) != 0;\r
430                 } \r
431 \r
432                 /// <summary>\r
433                 /// Returns true if the specified character is a valid name\r
434                 /// character as defined by production [4] in the XML 1.0 specification.\r
435                 /// </summary>\r
436                 /// <param name="c">The character to check.</param>\r
437                 public static bool IsNameChar(char c) \r
438                 {\r
439                         return (CHARS[c] & NAME) != 0;\r
440                 } \r
441 \r
442                 public static bool IsNameChar(int c) \r
443                 {\r
444                         return c > 0 && c < CHARS.Length && (CHARS[c] & NAME) != 0;\r
445                 } \r
446 \r
447                 /// <summary>\r
448                 /// Returns true if the specified character is a valid NCName start\r
449                 /// character as defined by production [4] in Namespaces in XML\r
450                 /// recommendation.\r
451                 /// </summary>\r
452                 /// <param name="c">The character to check.</param>\r
453                 /// <returns></returns>\r
454                 public static bool IsNCNameStart(char c) \r
455                 {\r
456                         return (CHARS[c] & NCNAME_START) != 0;\r
457                 }\r
458 \r
459                 public static bool IsNCNameStart(int c) \r
460                 {\r
461                         return c > 0 && c < CHARS.Length && (CHARS[c] & NCNAME_START) != 0;\r
462                 }\r
463 \r
464                 /// <summary>\r
465                 /// Returns true if the specified character is a valid NCName\r
466                 /// character as defined by production [5] in Namespaces in XML\r
467                 /// recommendation.\r
468                 /// </summary>\r
469                 /// <param name="c"></param>\r
470                 /// <returns></returns>\r
471                 public static bool IsNCNameChar(char c) \r
472                 {\r
473                         return (CHARS[c] & NCNAME) != 0;\r
474                 } \r
475 \r
476                 public static bool IsNCNameChar(int c) \r
477                 {\r
478                         return c > 0 && c < CHARS.Length && (CHARS[c] & NCNAME) != 0;\r
479                 } \r
480 \r
481                 /// <summary>\r
482                 /// Returns true if the specified character is a valid Pubid\r
483                 /// character as defined by production [13] in the XML 1.0 specification.\r
484                 /// </summary>\r
485                 /// <param name="c">The character to check</param>\r
486                 public static bool IsPubidChar (char c) \r
487                 {\r
488                         return (CHARS[c] & PUBID) != 0;\r
489                 }\r
490 \r
491                 public static bool IsPubidChar (int c) \r
492                 {\r
493                         return c > 0 && c < CHARS.Length && (CHARS[c] & PUBID) != 0;\r
494                 }\r
495 \r
496                 /// <summary>\r
497                 /// Check to see if a string is a valid Name according to [5]\r
498                 /// in the XML 1.0 Recommendation\r
499                 /// </summary>\r
500                 /// <param name="name">The string to check</param>\r
501                 public static bool IsValidName(String name, out Exception err) \r
502                 {\r
503                         err = null;\r
504                         if (name.Length == 0)\r
505                         {\r
506                                 err = new XmlException("Name can not be an empty string",null);\r
507                                 return false;\r
508                         }\r
509                         char ch = name[0];\r
510                         if( IsFirstNameChar (ch) == false)\r
511                         {\r
512                                 err = new XmlException("The character '"+ch+"' cannot start a Name",null);\r
513                                 return false;\r
514                         }\r
515                         for (int i = 1; i < name.Length; i++ ) \r
516                         {\r
517                                 ch = name[i];\r
518                                 if( IsNameChar (ch) == false )\r
519                                 {\r
520                                         err = new XmlException("The character '"+ch+"' is not allowed in a Name",null);\r
521                                         return false;\r
522                                 }\r
523                         }\r
524                         return true;\r
525                 }\r
526 \r
527                 public static int IsValidName (string name)\r
528                 {\r
529                         if (name.Length == 0)\r
530                                 return 0;\r
531                         if (!IsFirstNameChar (name [0]))\r
532                                 return 0;\r
533                         for (int i=1; i<name.Length; i++)\r
534                                 if (!IsNameChar (name [i]))\r
535                                         return i;\r
536                         return -1;\r
537                 }\r
538 \r
539                 /// <summary>\r
540                 /// Check to see if a string is a valid NCName according to [4]\r
541                 /// from the XML Namespaces 1.0 Recommendation\r
542                 /// </summary>\r
543                 /// <param name="ncName">The string to check</param>\r
544                 public static bool IsValidNCName(String ncName, out Exception err) \r
545                 {\r
546                         err = null;\r
547                         if (ncName.Length == 0)\r
548                         {\r
549                                 err = new XmlException("NCName can not be an empty string",null);\r
550                                 return false;\r
551                         }\r
552                         char ch = ncName[0];\r
553                         if( IsNCNameStart(ch) == false)\r
554                         {\r
555                                 err = new XmlException("The character '"+ch+"' cannot start a NCName",null);\r
556                                 return false;\r
557                         }\r
558                         for (int i = 1; i < ncName.Length; i++ ) \r
559                         {\r
560                                 ch = ncName[i];\r
561                                 if( IsNCNameChar (ch) == false )\r
562                                 {\r
563                                         err = new XmlException("The character '"+ch+"' is not allowed in a NCName",null);\r
564                                         return false;\r
565                                 }\r
566                         }\r
567                         return true;\r
568                 }\r
569 \r
570                 /// <summary>\r
571                 /// Check to see if a string is a valid Nmtoken according to [7]\r
572                 /// in the XML 1.0 Recommendation\r
573                 /// </summary>\r
574                 /// <param name="nmtoken">The string to check.</param>\r
575                 public static bool IsValidNmtoken(String nmtoken, out Exception err) \r
576                 {\r
577                         err = null;\r
578                         if (nmtoken.Length == 0)\r
579                         {\r
580                                 err = new XmlException("NMTOKEN can not be an empty string", null);\r
581                                 return false;\r
582                         }\r
583                         for (int i = 0; i < nmtoken.Length; i++ ) \r
584                         {\r
585                                 char ch = nmtoken[i];\r
586                                 if(  ! IsNameChar (ch) )\r
587                                 {\r
588                                         err = new XmlException("The character '"+ch+"' is not allowed in a NMTOKEN",null);\r
589                                         return false;\r
590                                 }\r
591                         }\r
592                         return true;\r
593                 }\r
594 \r
595                 // encodings\r
596 \r
597                 /// <summary>\r
598                 /// Returns true if the encoding name is a valid IANA encoding.\r
599                 /// This method does not verify that there is a decoder available\r
600                 /// for this encoding, only that the characters are valid for an\r
601                 /// IANA encoding name.\r
602                 /// </summary>\r
603                 /// <param name="ianaEncoding">The encoding to check.</param>\r
604                 /// <returns></returns>\r
605                 public static bool IsValidIANAEncoding(String ianaEncoding) \r
606                 {\r
607                         if (ianaEncoding != null) \r
608                         {\r
609                                 int length = ianaEncoding.Length;\r
610                                 if (length > 0) \r
611                                 {\r
612                                         char c = ianaEncoding[0];\r
613                                         if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) \r
614                                         {\r
615                                                 for (int i = 1; i < length; i++) \r
616                                                 {\r
617                                                         c = ianaEncoding[i];\r
618                                                         if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&\r
619                                                                 (c < '0' || c > '9') && c != '.' && c != '_' &&\r
620                                                                 c != '-') \r
621                                                         {\r
622                                                                 return false;\r
623                                                         }\r
624                                                 }\r
625                                                 return true;\r
626                                         }\r
627                                 }\r
628                         }\r
629                         return false;\r
630                 }\r
631 \r
632                 public static bool IsName (string str)\r
633                 {\r
634                         if (str.Length == 0)\r
635                                 return false;\r
636                         if (!IsFirstNameChar (str [0]))\r
637                                 return false;\r
638                         for (int i = 1; i < str.Length; i++)\r
639                                 if (!IsNameChar (str [i]))\r
640                                         return false;\r
641                         return true;\r
642                 }\r
643 \r
644                 public static bool IsNCName (string str)\r
645                 {\r
646                         if (str.Length == 0)\r
647                                 return false;\r
648                         if (!IsFirstNameChar (str [0]))\r
649                                 return false;\r
650                         for (int i = 0; i < str.Length; i++)\r
651                                 if (!IsNCNameChar (str [i]))\r
652                                         return false;\r
653                         return true;\r
654                 }\r
655 \r
656                 public static bool IsNmToken (string str)\r
657                 {\r
658                         if (str.Length == 0)\r
659                                 return false;\r
660                         for (int i = 0; i < str.Length; i++)\r
661                                 if (!IsNameChar (str [i]))\r
662                                         return false;\r
663                         return true;\r
664                 }\r
665 \r
666                 public static bool IsWhitespace (string str)\r
667                 {\r
668                         for (int i = 0; i < str.Length; i++)
669                                 if (!IsWhitespace (str [i])) return false;
670                                 \r
671                         return true;\r
672                 }\r
673 \r
674                 public static int GetPredefinedEntity (string name)\r
675                 {\r
676                         switch (name) {\r
677                         case "amp":\r
678                                 return '&';\r
679                         case "lt":\r
680                                 return '<';\r
681                         case "gt":\r
682                                 return '>';\r
683                         case "quot":\r
684                                 return '"';\r
685                         case "apos":\r
686                                 return '\'';\r
687                         default:\r
688                                 return -1;\r
689                         }\r
690                 }\r
691         }\r
692 }\r