unity3d减少播放器包含的 dll 文件
unity3d在构建播放器时(台式机、Android 或 iOS)有一点非常重要,也就是不要依赖 System.dll 或 System.Xml.dll。Unity 的播放器安装中不包含 System.dll 或 System.Xml.dll。这意味着,如果想要使用 Xml 或 System.dll 中的通用容器,那么必要的 dll 文件将包含在播放器中。这通常使得下载文件大小增加 1mb,这显然无益于播放器的分发,因而应该避免使用。如需解析一些 Xml 文件,可以使用更小的 xml 库,如 Mono.Xml.zip。大多数通用容器都包含在 mscorlib 中,Stack<> 和其他一小部分位于 System.dll。因此,应该尽量避免。
以下为源码MiniParse.cs
//
// System.Security.Cryptography.MiniParser: Internal XML parser implementation
//
// Authors:
// Sergey Chaban
//
// Copyright (c) 2001, 2002 Wild West Software
// Copyright (c) 2002 Sergey Chaban
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Text;
using System.Collections;
using System.Globalization;
namespace Mono.Xml {
internal class MiniParser {
public interface IReader {
int Read();
}
public interface IAttrList {
int Length {get;}
bool IsEmpty {get;}
string GetName(int i);
string GetValue(int i);
string GetValue(string name);
void ChangeValue(string name, string newValue);
string[] Names {get;}
string[] Values {get;}
}
public interface IMutableAttrList : IAttrList {
void Clear();
void Add(string name, string value);
void CopyFrom(IAttrList attrs);
void Remove(int i);
void Remove(string name);
}
public interface IHandler {
void OnStartParsing(MiniParser parser);
void OnStartElement(string name, IAttrList attrs);
void OnEndElement(string name);
void OnChars(string ch);
void OnEndParsing(MiniParser parser);
}
public class HandlerAdapter : IHandler {
public HandlerAdapter() {}
public void OnStartParsing(MiniParser parser) {}
public void OnStartElement(string name, IAttrList attrs) {}
public void OnEndElement(string name) {}
public void OnChars(string ch) {}
public void OnEndParsing(MiniParser parser) {}
}
private enum CharKind : byte {
LEFT_BR = 0,
RIGHT_BR = 1,
SLASH = 2,
PI_MARK = 3,
EQ = 4,
AMP = 5,
SQUOTE = 6,
DQUOTE = 7,
BANG = 8,
LEFT_SQBR = 9,
SPACE = 0xA,
RIGHT_SQBR = 0xB,
TAB = 0xC,
CR = 0xD,
EOL = 0xE,
CHARS = 0xF,
UNKNOWN = 0x1F
}
private enum ActionCode : byte {
START_ELEM = 0,
END_ELEM = 1,
END_NAME = 2,
SET_ATTR_NAME = 3,
SET_ATTR_VAL = 4,
SEND_CHARS = 5,
START_CDATA = 6,
END_CDATA = 7,
ERROR = 8,
STATE_CHANGE = 9,
FLUSH_CHARS_STATE_CHANGE = 0xA,
ACC_CHARS_STATE_CHANGE = 0xB,
ACC_CDATA = 0xC,
PROC_CHAR_REF = 0xD,
UNKNOWN = 0xF
}
public class AttrListImpl : IMutableAttrList {
protected ArrayList names;
protected ArrayList values;
public AttrListImpl() : this(0) {}
public AttrListImpl(int initialCapacity) {
if (initialCapacity <= 0) {
names = new ArrayList();
values = new ArrayList();
} else {
names = new ArrayList(initialCapacity);
values = new ArrayList(initialCapacity);
}
}
public AttrListImpl(IAttrList attrs)
: this(attrs != null ? attrs.Length : 0) {
if (attrs != null) this.CopyFrom(attrs);
}
public int Length {
get {return names.Count;}
}
public bool IsEmpty {
get {return this.Length != 0;}
}
public string GetName(int i) {
string res = null;
if (i >= 0 && i < this.Length) {
res = names[i] as string;
}
return res;
}
public string GetValue(int i) {
string res = null;
if (i >= 0 && i < this.Length) {
res = values[i] as string;
}
return res;
}
public string GetValue(string name) {
return this.GetValue(names.IndexOf(name));
}
public void ChangeValue(string name, string newValue) {
int i = names.IndexOf(name);
if (i >= 0 && i < this.Length) {
values[i] = newValue;
}
}
public string[] Names {
get {return names.ToArray(typeof(string)) as string[];}
}
public string[] Values {
get {return values.ToArray(typeof(string)) as string[];}
}
public void Clear() {
names.Clear();
values.Clear();
}
public void Add(string name, string value) {
names.Add(name);
values.Add(value);
}
public void Remove(int i) {
if (i >= 0) {
names.RemoveAt(i);
values.RemoveAt(i);
}
}
public void Remove(string name) {
this.Remove(names.IndexOf(name));
}
public void CopyFrom(IAttrList attrs) {
if (attrs != null && ((object)this == (object)attrs)) {
this.Clear();
int n = attrs.Length;
for (int i = 0; i < n; i++) {
this.Add(attrs.GetName(i), attrs.GetValue(i));
}
}
}
}
public class XMLError : Exception {
protected string descr;
protected int line, column;
public XMLError() : this("Unknown") {}
public XMLError(string descr) : this(descr, -1, -1) {}
public XMLError(string descr, int line, int column)
: base(descr) {
this.descr = descr;
this.line = line;
this.column = column;
}
public int Line {get {return line;}}
public int Column {get {return column;}}
public override string ToString() {
return (String.Format("{0} @ (line = {1}, col = {2})", descr, line, column));
}
}
private static readonly int INPUT_RANGE = 13;
private static readonly ushort[] tbl = {
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(ushort)(((ushort)CharKind.CHARS << 12) | ((ushort)ActionCode.UNKNOWN << 8) | 255),
0xFFFF
};
protected static string[] errors = {
/* 0 */ "Expected element",
/* 1 */ "Invalid character in tag",
/* 2 */ "No '='",
/* 3 */ "Invalid character entity",
/* 4 */ "Invalid attr value",
/* 5 */ "Empty tag",
/* 6 */ "No end tag",
/* 7 */ "Bad entity ref"
};
protected int line;
protected int col;
protected int[] twoCharBuff;
protected bool splitCData;
public MiniParser() {
twoCharBuff = new int[2];
splitCData = false;
Reset();
}
public void Reset() {
line = 0;
col = 0;
}
protected static bool StrEquals(string str, StringBuilder sb, int sbStart, int len) {
if (len != str.Length) return false;
for (int i = 0; i < len; i++) {
if (str[i] != sb[sbStart + i]) return false;
}
return true;
}
protected void FatalErr(string descr) {
throw new XMLError(descr, this.line, this.col);
}
protected static int Xlat(int charCode, int state) {
int p = state * INPUT_RANGE;
int n = System.Math.Min(tbl.Length - p, INPUT_RANGE);
for (;--n >= 0;) {
ushort code = tbl[p];
if (charCode == (code >> 12)) return (code & 0xFFF);
p++;
}
return 0xFFF;
}
public void Parse(IReader reader, IHandler handler) {
if (reader == null) throw new ArgumentNullException("reader");
if (handler == null) handler = new HandlerAdapter();
AttrListImpl attrList = new AttrListImpl();
string lastAttrName = null;
Stack tagStack = new Stack();
string elementName = null;
line = 1;
col = 0;
int currCh = 0;
int stateCode = 0;
StringBuilder sbChars = new StringBuilder();
bool seenCData = false;
bool isComment = false;
bool isDTD = false;
int bracketSwitch = 0;
handler.OnStartParsing(this);
while (true) {
++this.col;
currCh = reader.Read();
if (currCh == -1) {
if (stateCode != 0) {
FatalErr("Unexpected EOF");
}
break;
}
int charCode = "<>/?=&'\"![ ]\t\r\n".IndexOf((char)currCh) & 0xF;
if (charCode == (int)CharKind.CR) continue; // ignore
// whitepace ::= (#x20 | #x9 | #xd | #xa)+
if (charCode == (int)CharKind.TAB) charCode = (int)CharKind.SPACE; // tab == space
if (charCode == (int)CharKind.EOL) {
this.col = 0;
this.line++;
charCode = (int)CharKind.SPACE;
}
int actionCode = MiniParser.Xlat(charCode, stateCode);
stateCode = actionCode & 0xFF;
// Ignore newline inside attribute value.
if (currCh == '\n' && (stateCode == 0xE || stateCode == 0xF)) continue;
actionCode >>= 8;
if (stateCode >= 0x80) {
if (stateCode == 0xFF) {
FatalErr("State dispatch error.");
} else {
FatalErr(errors[stateCode ^ 0x80]);
}
}
switch (actionCode) {
case (int)ActionCode.START_ELEM:
handler.OnStartElement(elementName, attrList);
if (currCh != '/') {
tagStack.Push(elementName);
} else {
handler.OnEndElement(elementName);
}
attrList.Clear();
break;
case (int)ActionCode.END_ELEM:
elementName = sbChars.ToString();
sbChars = new StringBuilder();
string endName = null;
if (tagStack.Count == 0 ||
elementName != (endName = tagStack.Pop() as string)) {
if (endName == null) {
FatalErr("Tag stack underflow");
} else {
FatalErr(String.Format("Expected end tag '{0}' but found '{1}'", elementName, endName));
}
}
handler.OnEndElement(elementName);
break;
case (int)ActionCode.END_NAME:
elementName = sbChars.ToString();
sbChars = new StringBuilder();
if (currCh != '/' && currCh != '>') break;
goto case (int)ActionCode.START_ELEM;
case (int)ActionCode.SET_ATTR_NAME:
lastAttrName = sbChars.ToString();
sbChars = new StringBuilder();
break;
case (int)ActionCode.SET_ATTR_VAL:
if (lastAttrName == null) FatalErr("Internal error.");
attrList.Add(lastAttrName, sbChars.ToString());
sbChars = new StringBuilder();
lastAttrName = null;
break;
case (int)ActionCode.SEND_CHARS:
handler.OnChars(sbChars.ToString());
sbChars = new StringBuilder();
break;
case (int)ActionCode.START_CDATA:
string cdata = "CDATA[";
isComment = false;
isDTD = false;
if (currCh == '-') {
currCh = reader.Read();
if (currCh != '-') FatalErr("Invalid comment");
this.col++;
isComment = true;
twoCharBuff[0] = -1;
twoCharBuff[1] = -1;
} else {
if (currCh != '[') {
isDTD = true;
bracketSwitch = 0;
break;
}
for (int i = 0; i < cdata.Length; i++) {
if (reader.Read() != cdata[i]) {
this.col += i+1;
break;
}
}
this.col += cdata.Length;
seenCData = true;
}
break;
case (int)ActionCode.END_CDATA:
int n = 0;
currCh = ']';
while (currCh == ']') {
currCh = reader.Read();
n++;
}
if (currCh != '>') {
for (int i = 0; i < n; i++) sbChars.Append(']');
sbChars.Append((char)currCh);
stateCode = 0x12;
} else {
for (int i = 0; i < n-2; i++) sbChars.Append(']');
seenCData = false;
}
this.col += n;
break;
case (int)ActionCode.ERROR:
FatalErr(String.Format("Error {0}", stateCode));
break;
case (int)ActionCode.STATE_CHANGE:
break;
case (int)ActionCode.FLUSH_CHARS_STATE_CHANGE:
sbChars = new StringBuilder();
if (currCh != '<') goto case (int)ActionCode.ACC_CHARS_STATE_CHANGE;
break;
case (int)ActionCode.ACC_CHARS_STATE_CHANGE:
sbChars.Append((char)currCh);
break;
case (int)ActionCode.ACC_CDATA:
if (isComment) {
if (currCh == '>'
&& twoCharBuff[0] == '-'
&& twoCharBuff[1] == '-') {
isComment = false;
stateCode = 0;
} else {
twoCharBuff[0] = twoCharBuff[1];
twoCharBuff[1] = currCh;
}
} else if (isDTD) {
if (currCh == '<' || currCh == '>') bracketSwitch ^= 1;
if (currCh == '>' && bracketSwitch != 0) {
isDTD = false;
stateCode = 0;
}
} else {
if (this.splitCData
&& sbChars.Length > 0
&& seenCData) {
handler.OnChars(sbChars.ToString());
sbChars = new StringBuilder();
}
seenCData = false;
sbChars.Append((char)currCh);
}
break;
case (int)ActionCode.PROC_CHAR_REF:
currCh = reader.Read();
int cl = this.col + 1;
if (currCh == '#') { // character reference
int r = 10;
int chCode = 0;
int nDigits = 0;
currCh = reader.Read();
cl++;
if (currCh == 'x') {
currCh = reader.Read();
cl++;
r=16;
}
NumberStyles style = r == 16 ? NumberStyles.HexNumber : NumberStyles.Integer;
while (true) {
int x = -1;
if (Char.IsNumber((char)currCh) || "abcdef".IndexOf(Char.ToLower((char)currCh)) != -1) {
try {
x = Int32.Parse(new string((char)currCh, 1), style);
} catch (FormatException) {x = -1;}
}
if (x == -1) break;
chCode *= r;
chCode += x;
nDigits++;
currCh = reader.Read();
cl++;
}
if (currCh == ';' && nDigits > 0) {
sbChars.Append((char)chCode);
} else {
FatalErr("Bad char ref");
}
} else {
// entity reference
string entityRefChars = "aglmopqstu"; // amp | apos | quot | gt | lt
string entities = "&'\"><";
int pos = 0;
int entIdx = 0xF;
int predShift = 0;
int sbLen = sbChars.Length;
while (true) {
if (pos != 0xF) pos = entityRefChars.IndexOf((char)currCh) & 0xF;
if (pos == 0xF) FatalErr(errors[7]);
sbChars.Append((char)currCh);
int path = "\uFF35\u3F8F\u4F8F\u0F5F\uFF78\uE1F4\u2299\uEEFF\uEEFF\uFF4F"[pos];
int lBr = (path >> 4) & 0xF;
int rBr = path & 0xF;
int lPred = path >> 12;
int rPred = (path >> 8) & 0xF;
currCh = reader.Read();
cl++;
pos = 0xF;
if (lBr != 0xF && currCh == entityRefChars[lBr]) {
if (lPred < 0xE) entIdx = lPred;
// pred = lPred;
predShift = 12; // left
} else if (rBr != 0xF && currCh == entityRefChars[rBr]) {
if (rPred < 0xE) entIdx = rPred;
// pred = rPred;
predShift = 8; // right
} else if (currCh == ';') {
if (entIdx != 0xF
&& predShift != 0
&& ((path >> predShift) & 0xF) == 0xE) break;
continue; // pos == 0xF
}
pos=0;
}
int l = cl - this.col - 1;
if ((l > 0 && l < 5)
&&(StrEquals("amp", sbChars, sbLen, l)
|| StrEquals("apos", sbChars, sbLen, l)
|| StrEquals("quot", sbChars, sbLen, l)
|| StrEquals("lt", sbChars, sbLen, l)
|| StrEquals("gt", sbChars, sbLen, l))
) {
sbChars.Length = sbLen;
sbChars.Append(entities[entIdx]);
} else FatalErr(errors[7]);
}
this.col = cl;
break;
default:
FatalErr(String.Format("Unexpected action code - {0}.", actionCode));
break;
}
} // while (true)
handler.OnEndParsing(this);
} // Parse
}
}
SecurityParser .cs
//
// Mono.Xml.SecurityParser.cs class implementation
//
// Author:
// Sebastien Pouliot (spouliot@motus.com)
//
// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
//
//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.IO;
using System.Security;
namespace Mono.Xml {
// convert an XML document into SecurityElement objects
internal class SecurityParser : SmallXmlParser, SmallXmlParser.IContentHandler {
private SecurityElement root;
public SecurityParser () : base ()
{
stack = new Stack ();
}
public void LoadXml (string xml)
{
root = null;
#if CF_1_0
stack = new Stack ();
#else
stack.Clear ();
#endif
Parse (new StringReader (xml), this);
}
public SecurityElement ToXml ()
{
return root;
}
// IContentHandler
private SecurityElement current;
private Stack stack;
public void OnStartParsing (SmallXmlParser parser) {}
public void OnProcessingInstruction (string name, string text) {}
public void OnIgnorableWhitespace (string s) {}
public void OnStartElement (string name, SmallXmlParser.IAttrList attrs)
{
SecurityElement newel = new SecurityElement (name);
if (root == null) {
root = newel;
current = newel;
}
else {
SecurityElement parent = (SecurityElement) stack.Peek ();
parent.AddChild (newel);
}
stack.Push (newel);
current = newel;
// attributes
int n = attrs.Length;
for (int i=0; i < n; i++)
current.AddAttribute (attrs.GetName (i), attrs.GetValue (i));
}
public void OnEndElement (string name)
{
current = (SecurityElement) stack.Pop ();
}
public void OnChars (string ch)
{
current.Text = ch;
}
public void OnEndParsing (SmallXmlParser parser) {}
}
}
SmallXmlParser.cs
//
// SmallXmlParser.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//
// small xml parser that is mostly compatible with
//
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Text;
namespace Mono.Xml
{
internal class DefaultHandler : SmallXmlParser.IContentHandler
{
public void OnStartParsing (SmallXmlParser parser)
{
}
public void OnEndParsing (SmallXmlParser parser)
{
}
public void OnStartElement (string name, SmallXmlParser.IAttrList attrs)
{
}
public void OnEndElement (string name)
{
}
public void OnChars (string s)
{
}
public void OnIgnorableWhitespace (string s)
{
}
public void OnProcessingInstruction (string name, string text)
{
}
}
internal class SmallXmlParser
{
public interface IContentHandler
{
void OnStartParsing (SmallXmlParser parser);
void OnEndParsing (SmallXmlParser parser);
void OnStartElement (string name, IAttrList attrs);
void OnEndElement (string name);
void OnProcessingInstruction (string name, string text);
void OnChars (string text);
void OnIgnorableWhitespace (string text);
}
public interface IAttrList
{
int Length { get; }
bool IsEmpty { get; }
string GetName (int i);
string GetValue (int i);
string GetValue (string name);
string [] Names { get; }
string [] Values { get; }
}
class AttrListImpl : IAttrList
{
public int Length {
get { return attrNames.Count; }
}
public bool IsEmpty {
get { return attrNames.Count == 0; }
}
public string GetName (int i)
{
return (string) attrNames [i];
}
public string GetValue (int i)
{
return (string) attrValues [i];
}
public string GetValue (string name)
{
for (int i = 0; i < attrNames.Count; i++)
if ((string) attrNames [i] == name)
return (string) attrValues [i];
return null;
}
public string [] Names {
get { return (string []) attrNames.ToArray (typeof (string)); }
}
public string [] Values {
get { return (string []) attrValues.ToArray (typeof (string)); }
}
ArrayList attrNames = new ArrayList ();
ArrayList attrValues = new ArrayList ();
internal void Clear ()
{
attrNames.Clear ();
attrValues.Clear ();
}
internal void Add (string name, string value)
{
attrNames.Add (name);
attrValues.Add (value);
}
}
IContentHandler handler;
TextReader reader;
Stack elementNames = new Stack ();
Stack xmlSpaces = new Stack ();
string xmlSpace;
StringBuilder buffer = new StringBuilder (200);
char [] nameBuffer = new char [30];
bool isWhitespace;
AttrListImpl attributes = new AttrListImpl ();
int line = 1, column;
bool resetColumn;
public SmallXmlParser ()
{
}
private Exception Error (string msg)
{
return new SmallXmlParserException (msg, line, column);
}
private Exception UnexpectedEndError ()
{
string [] arr = new string [elementNames.Count];
// COMPACT FRAMEWORK NOTE: CopyTo is not visible through the Stack class
(elementNames as ICollection).CopyTo (arr, 0);
return Error (String.Format (
"Unexpected end of stream. Element stack content is {0}", String.Join (",", arr)));
}
private bool IsNameChar (char c, bool start)
{
switch (c) {
case ':':
case '_':
return true;
case '-':
case '.':
return !start;
}
if (c > 0x100) { // optional condition for optimization
switch (c) {
case '\u0559':
case '\u06E5':
case '\u06E6':
return true;
}
if ('\u02BB' <= c && c <= '\u02C1')
return true;
}
switch (Char.GetUnicodeCategory (c)) {
case UnicodeCategory.LowercaseLetter:
case UnicodeCategory.UppercaseLetter:
case UnicodeCategory.OtherLetter:
case UnicodeCategory.TitlecaseLetter:
case UnicodeCategory.LetterNumber:
return true;
case UnicodeCategory.SpacingCombiningMark:
case UnicodeCategory.EnclosingMark:
case UnicodeCategory.NonSpacingMark:
case UnicodeCategory.ModifierLetter:
case UnicodeCategory.DecimalDigitNumber:
return !start;
default:
return false;
}
}
private bool IsWhitespace (int c)
{
switch (c) {
case ' ':
case '\r':
case '\t':
case '\n':
return true;
default:
return false;
}
}
public void SkipWhitespaces ()
{
SkipWhitespaces (false);
}
private void HandleWhitespaces ()
{
while (IsWhitespace (Peek ()))
buffer.Append ((char) Read ());
if (Peek () != '<' && Peek () >= 0)
isWhitespace = false;
}
public void SkipWhitespaces (bool expected)
{
while (true) {
switch (Peek ()) {
case ' ':
case '\r':
case '\t':
case '\n':
Read ();
if (expected)
expected = false;
continue;
}
if (expected)
throw Error ("Whitespace is expected.");
return;
}
}
private int Peek ()
{
return reader.Peek ();
}
private int Read ()
{
int i = reader.Read ();
if (i == '\n')
resetColumn = true;
if (resetColumn) {
line++;
resetColumn = false;
column = 1;
}
else
column++;
return i;
}
public void Expect (int c)
{
int p = Read ();
if (p < 0)
throw UnexpectedEndError ();
else if (p != c)
throw Error (String.Format ("Expected '{0}' but got {1}", (char) c, (char) p));
}
private string ReadUntil (char until, bool handleReferences)
{
while (true) {
if (Peek () < 0)
throw UnexpectedEndError ();
char c = (char) Read ();
if (c == until)
break;
else if (handleReferences && c == '&')
ReadReference ();
else
buffer.Append (c);
}
string ret = buffer.ToString ();
buffer.Length = 0;
return ret;
}
public string ReadName ()
{
int idx = 0;
if (Peek () < 0 || !IsNameChar ((char) Peek (), true))
throw Error ("XML name start character is expected.");
for (int i = Peek (); i >= 0; i = Peek ()) {
char c = (char) i;
if (!IsNameChar (c, false))
break;
if (idx == nameBuffer.Length) {
char [] tmp = new char [idx * 2];
// COMPACT FRAMEWORK NOTE: Array.Copy(sourceArray, destinationArray, count) is not available.
Array.Copy (nameBuffer, 0, tmp, 0, idx);
nameBuffer = tmp;
}
nameBuffer [idx++] = c;
Read ();
}
if (idx == 0)
throw Error ("Valid XML name is expected.");
return new string (nameBuffer, 0, idx);
}
public void Parse (TextReader input, IContentHandler handler)
{
this.reader = input;
this.handler = handler;
handler.OnStartParsing (this);
while (Peek () >= 0)
ReadContent ();
HandleBufferedContent ();
if (elementNames.Count > 0)
throw Error (String.Format ("Insufficient close tag: {0}", elementNames.Peek ()));
handler.OnEndParsing (this);
Cleanup ();
}
private void Cleanup ()
{
line = 1;
column = 0;
handler = null;
reader = null;
#if CF_1_0
elementNames = new Stack ();
xmlSpaces = new Stack ();
#else
elementNames.Clear ();
xmlSpaces.Clear ();
#endif
attributes.Clear ();
buffer.Length = 0;
xmlSpace = null;
isWhitespace = false;
}
public void ReadContent ()
{
string name;
if (IsWhitespace (Peek ())) {
if (buffer.Length == 0)
isWhitespace = true;
HandleWhitespaces ();
}
if (Peek () == '<') {
Read ();
switch (Peek ()) {
case '!': // declarations
Read ();
if (Peek () == '[') {
Read ();
if (ReadName () != "CDATA")
throw Error ("Invalid declaration markup");
Expect ('[');
ReadCDATASection ();
return;
}
else if (Peek () == '-') {
ReadComment ();
return;
}
else if (ReadName () != "DOCTYPE")
throw Error ("Invalid declaration markup.");
else
throw Error ("This parser does not support document type.");
case '?': // PIs
HandleBufferedContent ();
Read ();
name = ReadName ();
SkipWhitespaces ();
string text = String.Empty;
if (Peek () != '?') {
while (true) {
text += ReadUntil ('?', false);
if (Peek () == '>')
break;
text += "?";
}
}
handler.OnProcessingInstruction (
name, text);
Expect ('>');
return;
case '/': // end tags
HandleBufferedContent ();
if (elementNames.Count == 0)
throw UnexpectedEndError ();
Read ();
name = ReadName ();
SkipWhitespaces ();
string expected = (string) elementNames.Pop ();
xmlSpaces.Pop ();
if (xmlSpaces.Count > 0)
xmlSpace = (string) xmlSpaces.Peek ();
else
xmlSpace = null;
if (name != expected)
throw Error (String.Format ("End tag mismatch: expected {0} but found {1}", expected, name));
handler.OnEndElement (name);
Expect ('>');
return;
default: // start tags (including empty tags)
HandleBufferedContent ();
name = ReadName ();
while (Peek () != '>' && Peek () != '/')
ReadAttribute (attributes);
handler.OnStartElement (name, attributes);
attributes.Clear ();
SkipWhitespaces ();
if (Peek () == '/') {
Read ();
handler.OnEndElement (name);
}
else {
elementNames.Push (name);
xmlSpaces.Push (xmlSpace);
}
Expect ('>');
return;
}
}
else
ReadCharacters ();
}
private void HandleBufferedContent ()
{
if (buffer.Length == 0)
return;
if (isWhitespace)
handler.OnIgnorableWhitespace (buffer.ToString ());
else
handler.OnChars (buffer.ToString ());
buffer.Length = 0;
isWhitespace = false;
}
private void ReadCharacters ()
{
isWhitespace = false;
while (true) {
int i = Peek ();
switch (i) {
case -1:
return;
case '<':
return;
case '&':
Read ();
ReadReference ();
continue;
default:
buffer.Append ((char) Read ());
continue;
}
}
}
private void ReadReference ()
{
if (Peek () == '#') {
// character reference
Read ();
ReadCharacterReference ();
} else {
string name = ReadName ();
Expect (';');
switch (name) {
case "amp":
buffer.Append ('&');
break;
case "quot":
buffer.Append ('"');
break;
case "apos":
buffer.Append ('\'');
break;
case "lt":
buffer.Append ('<');
break;
case "gt":
buffer.Append ('>');
break;
default:
throw Error ("General non-predefined entity reference is not supported in this parser.");
}
}
}
private int ReadCharacterReference ()
{
int n = 0;
if (Peek () == 'x') { // hex
Read ();
for (int i = Peek (); i >= 0; i = Peek ()) {
if ('0' <= i && i <= '9')
n = n << 4 + i - '0';
else if ('A' <= i && i <='F')
n = n << 4 + i - 'A' + 10;
else if ('a' <= i && i <='f')
n = n << 4 + i - 'a' + 10;
else
break;
Read ();
}
} else {
for (int i = Peek (); i >= 0; i = Peek ()) {
if ('0' <= i && i <= '9')
n = n << 4 + i - '0';
else
break;
Read ();
}
}
return n;
}
private void ReadAttribute (AttrListImpl a)
{
SkipWhitespaces (true);
if (Peek () == '/' || Peek () == '>')
// came here just to spend trailing whitespaces
return;
string name = ReadName ();
string value;
SkipWhitespaces ();
Expect ('=');
SkipWhitespaces ();
switch (Read ()) {
case '\'':
value = ReadUntil ('\'', true);
break;
case '"':
value = ReadUntil ('"', true);
break;
default:
throw Error ("Invalid attribute value markup.");
}
if (name == "xml:space")
xmlSpace = value;
a.Add (name, value);
}
private void ReadCDATASection ()
{
int nBracket = 0;
while (true) {
if (Peek () < 0)
throw UnexpectedEndError ();
char c = (char) Read ();
if (c == ']')
nBracket++;
else if (c == '>' && nBracket > 1) {
for (int i = nBracket; i > 2; i--)
buffer.Append (']');
break;
}
else {
for (int i = 0; i < nBracket; i++)
buffer.Append (']');
nBracket = 0;
buffer.Append (c);
}
}
}
private void ReadComment ()
{
Expect ('-');
Expect ('-');
while (true) {
if (Read () != '-')
continue;
if (Read () != '-')
continue;
if (Read () != '>')
throw Error ("'--' is not allowed inside comment markup.");
break;
}
}
}
internal class SmallXmlParserException : SystemException
{
int line;
int column;
public SmallXmlParserException (string msg, int line, int column)
: base (String.Format ("{0}. At ({1},{2})", msg, line, column))
{
this.line = line;
this.column = column;
}
public int Line {
get { return line; }
}
public int Column {
get { return column; }
}
}
}