public QName GetQName(string local, string nsUri, string prefix) { nsUri = nameTable.Add(nsUri); prefix = nameTable.Add(prefix); List<QName> list; if (!qnames.TryGetValue(local, out list)) { list = new List<QName>(); qnames.Add(local, list); } else { foreach (QName qn in list) { Debug.Assert(qn.Local == local, "Atomization Failure: '" + local + "'"); if (RefEquals(qn.Prefix, prefix) && RefEquals(qn.NsUri, nsUri)) { return qn; } } } QName qname = new QName(nameTable.Add(local), nsUri, prefix); list.Add(qname); return qname; }
public void Reset() { lastRecord = 0; records[lastRecord++] = new QName(null, nameTable.Add(NsXml), nameTable.Add("xml")); // xmlns:xml="http://www.w3.org/XML/1998/namespace" records[lastRecord++] = new QName(null, stringEmpty, stringEmpty); // xml="" records[lastRecord++] = new QName(stringEmpty, stringEmpty, stringEmpty); // -- lookup barier }
public BufferWriter(TokenPipe pipe, XmlNameTable nameTable) { this.pipe = pipe; this.qnameTable = new QNameTable(nameTable); this.sbuilder = new StringBuilder(); QNameXmlSpace = qnameTable.GetQName("space", NsXml, "xml"); // xml:space QNameXmlLang = qnameTable.GetQName("lang", NsXml, "xml"); // xml:lang QNameXmlNs = qnameTable.GetQName("xmlns", NsXmlNs, ""); // xmlsn="" QNameEmpty = qnameTable.GetQName("", "", ""); }
public override void WriteStartAttribute(string prefix, string name, string ns) { curAttribute = qnameTable.GetQName(name, ns, prefix); }
// it seams that it faster to set fields of structure in one call. // This trick is workaround of the C# limitation of declaring variable as ref to a struct. public static void Set(ref XmlToken evnt, XmlNodeType nodeType, QName name, string value) { evnt.NodeType = nodeType; evnt.Name = name; evnt.Value = value; }
public static void Get(ref XmlToken evnt, out XmlNodeType nodeType, out QName name, out string value) { nodeType = evnt.NodeType; name = evnt.Name; value = evnt.Value; }
/// <summary>See <see cref="XmlReader.MoveToAttribute(string, string)"/>.</summary> public override bool MoveToAttribute(string name, string ns) { if (IsInsideElement()) { for (int i = 1; i <= attCount; i++) { QName attName; string attValue; pipe.GetToken(i, out attName, out attValue); if (attName.Local == name && attName.NsUri == ns) { ChangeDepthToElement(); nodeType = XmlNodeType.Attribute; attOffset = i; qname = attName; depth++; value = attValue; } } } return false; }
public virtual void Read(out XmlNodeType nodeType, out QName name, out string value) { Debug.Assert(readEndPos < buffer.Length); XmlToken.Get(ref buffer[readEndPos], out nodeType, out name, out value); readEndPos++; }
void SetUndefinedState(ReadState readState) { this.qname = writer.QNameEmpty; this.value = string.Empty; this.nodeType = XmlNodeType.None; this.attCount = 0; this.readState = readState; }
/// <summary> /// See <see cref="XmlReader.Read()"/>. /// </summary> public override bool Read() { // Leave Current node switch (nodeType) { case XmlNodeType.None: if (readState == ReadState.EndOfFile || readState == ReadState.Closed) { return false; } readState = ReadState.Interactive; break; case XmlNodeType.Attribute: attOffset = 0; depth--; goto case XmlNodeType.Element; case XmlNodeType.Element: pipe.FreeTokens(1 + attCount); depth++; break; case XmlNodeType.EndElement: scope.PopScope(); pipe.FreeTokens(1); break; case XmlNodeType.Text: if (attOffset != 0) { // We are on text node inside of the attribute attOffset = 0; depth -= 2; goto case XmlNodeType.Element; } pipe.FreeTokens(1); break; case XmlNodeType.ProcessingInstruction: case XmlNodeType.Comment: case XmlNodeType.SignificantWhitespace: case XmlNodeType.Whitespace: pipe.FreeTokens(1); break; default: throw new InvalidProgramException("Internal Error: unexpected node type"); } Debug.Assert(attOffset == 0); Debug.Assert(readState == ReadState.Interactive); attCount = 0; // Step on next node pipe.Read(out nodeType, out qname, out value); if (nodeType == XmlNodeType.None) { SetUndefinedState(ReadState.EndOfFile); return false; } switch (nodeType) { case XmlNodeType.Element: for (attCount = 0; true; attCount++) { XmlNodeType attType; QName attName; string attText; pipe.Read(out attType, out attName, out attText); if (attType != XmlNodeType.Attribute) { break; // We are done with attributes for this element } if (RefEquals(attName.Prefix, "xmlns")) { scope.AddNamespace(attName.Local, attText); } else if (RefEquals(attName, writer.QNameXmlNs)) { scope.AddNamespace(attName.Prefix, attText); } // prefix is atomized empty string else if (RefEquals(attName, writer.QNameXmlLang)) { scope.AddLang(attText); } else if (RefEquals(attName, writer.QNameXmlSpace)) { scope.AddSpace(attText); } } scope.PushScope(qname); break; case XmlNodeType.EndElement: qname = scope.Name; depth--; break; case XmlNodeType.Comment: case XmlNodeType.ProcessingInstruction: break; case XmlNodeType.Text: if (IsWhitespace(value)) { nodeType = XmlSpace == XmlSpace.Preserve ? XmlNodeType.SignificantWhitespace : XmlNodeType.Whitespace; } break; default: throw new InvalidProgramException("Internal Error: unexpected node type"); } return true; }
public override void GetToken(int attNum, out QName name, out string value) { Debug.Assert(0 <= attNum && attNum < readEndPos - readStartPos - 1); XmlNodeType nodeType; XmlToken.Get(ref buffer[(readStartPos + attNum) & mask], out nodeType, out name, out value); Debug.Assert(nodeType == (attNum == 0 ? XmlNodeType.Element : XmlNodeType.Attribute), "We use GetToken() only to access parts of start element tag."); }
public override void Read(out XmlNodeType nodeType, out QName name, out string value) { lock (this) { Debug.Assert(readEndPos <= writePos && writePos <= readStartPos + buffer.Length); if (readEndPos == writePos) { if (readEndPos == readStartPos + buffer.Length) { ExpandBuffer(); Monitor.Pulse(this); } Monitor.Wait(this); } if (exception != null) { throw new XsltException("Exception happened during transformation. See inner exception for details:\n", exception); } } Debug.Assert(readEndPos < writePos); XmlToken.Get(ref buffer[readEndPos & mask], out nodeType, out name, out value); readEndPos++; }
public override void Write(XmlNodeType nodeType, QName name, string value) { lock (this) { Debug.Assert(readEndPos <= writePos && writePos <= readStartPos + buffer.Length); if (writePos == readStartPos + buffer.Length) { if (writePos == readEndPos) { ExpandBuffer(); } else { Monitor.Wait(this); } } Debug.Assert(writePos < readStartPos + buffer.Length); XmlToken.Set(ref buffer[writePos & mask], nodeType, name, value); writePos++; if (readStartPos + buffer.Length <= writePos) { // This "if" is some heuristics, it may wrk or may not: // To minimize task switching we wakeup reader ony if we wrote enouph tokens. // So if reader already waits, let it sleep before we fill up the buffer. Monitor.Pulse(this); } } }
public void PushScope(QName qname) { Debug.Assert(qname.Local != null, "Scope is Element Name"); AddRecord(qname); }
private static bool RefEquals(QName qnA, QName qnB) { Debug.Assert( ((object)qnA == (object)qnB) || qnA.Local != qnB.Local || qnA.NsUri != qnB.NsUri || qnA.Prefix != qnB.Prefix, "QName atomization Failure: '" + qnA.ToString() + "'" ); return (object)qnA == (object)qnB; }
private void AddRecord(QName qname) { if (lastRecord == records.Length) { QName[] temp = new QName[records.Length * 2]; records.CopyTo(temp, 0); records = temp; } records[lastRecord++] = qname; }
public virtual void Write(XmlNodeType nodeType, QName name, string value) { Debug.Assert(writePos <= buffer.Length); if (writePos == buffer.Length) { XmlToken[] temp = new XmlToken[buffer.Length * 2]; buffer.CopyTo(temp, 0); buffer = temp; } Debug.Assert(writePos < buffer.Length); XmlToken.Set(ref buffer[writePos], nodeType, name, value); writePos++; }