/// <summary> /// Return a following sibling of the specified node that has the specified type. If no such /// sibling exists, then do not set pageNode or idxNode and return false. /// </summary> public static bool GetContentSibling(ref XPathNode[] pageNode, ref int idxNode, XPathNodeType typ) { XPathNode[] page = pageNode; int idx = idxNode; int mask = XPathNavigator.GetContentKindMask(typ); Debug.Assert(pageNode != null && idxNode != 0, "Cannot pass null argument(s)"); if (page[idx].NodeType != XPathNodeType.Attribute) { while (true) { idx = page[idx].GetSibling(out page); if (idx == 0) { break; } if (((1 << (int)page[idx].NodeType) & mask) != 0) { Debug.Assert(typ != XPathNodeType.Attribute && typ != XPathNodeType.Namespace); pageNode = page; idxNode = idx; return(true); } } } return(false); }
/// <summary> /// Return a previous sibling of the specified node that has the specified type. If no such /// sibling exists, then do not set pageNode or idxNode and return false. /// </summary> public static bool GetPreviousContentSibling(ref XPathNode[] pageNode, ref int idxNode, XPathNodeType typ) { XPathNode[] page = pageNode; int idx = idxNode; int mask = XPathNavigator.GetContentKindMask(typ); Debug.Assert(pageNode != null && idxNode != 0, "Cannot pass null argument(s)"); while (true) { if (!GetPreviousContentSibling(ref page, ref idx)) { break; } if (((1 << (int)page[idx].NodeType) & mask) != 0) { pageNode = page; idxNode = idx; return(true); } } return(false); }
public static bool GetContentChild(ref XPathNode[] pageNode, ref int idxNode, XPathNodeType typ) { XPathNode[] nodeArray = pageNode; int index = idxNode; if (nodeArray[index].HasContentChild) { int contentKindMask = XPathNavigator.GetContentKindMask(typ); GetChild(ref nodeArray, ref index); do { if (((((int)1) << nodeArray[index].NodeType) & contentKindMask) != 0) { if (typ == XPathNodeType.Attribute) { return(false); } pageNode = nodeArray; idxNode = index; return(true); } index = nodeArray[index].GetSibling(out nodeArray); }while (index != 0); } return(false); }
/// <summary> /// Return the first child of the specified node that has the specified type (must be a content type). If no such /// child exists, then do not set pageNode or idxNode and return false. /// </summary> public static bool GetContentChild(ref XPathNode[] pageNode, ref int idxNode, XPathNodeType typ) { XPathNode[] page = pageNode; int idx = idxNode; int mask; Debug.Assert(pageNode != null && idxNode != 0, "Cannot pass null argument(s)"); // Only check children if at least one content-typed child exists if (page[idx].HasContentChild) { mask = XPathNavigator.GetContentKindMask(typ); GetChild(ref page, ref idx); do { if (((1 << (int)page[idx].NodeType) & mask) != 0) { // Never return attributes, as Attribute is not a content type if (typ == XPathNodeType.Attribute) { return(false); } pageNode = page; idxNode = idx; return(true); } idx = page[idx].GetSibling(out page); }while (idx != 0); } return(false); }
/// <summary> /// Get the next node that: /// 1. Follows the current node in document order (includes descendants, unlike XPath following axis) /// 2. Precedes the ending node in document order (if pageEnd is null, then all following nodes in the document are considered) /// 3. Has the specified XPathNodeType (but Attributes and Namespaces never match) /// If no such node exists, then do not set pageCurrent or idxCurrent and return false. /// </summary> public static bool GetContentFollowing(ref XPathNode[] pageCurrent, ref int idxCurrent, XPathNode[] pageEnd, int idxEnd, XPathNodeType typ) { XPathNode[] page = pageCurrent; int idx = idxCurrent; int mask = XPathNavigator.GetContentKindMask(typ); Debug.Assert(pageCurrent != null && idxCurrent != 0, "Cannot pass null argument(s)"); Debug.Assert(typ != XPathNodeType.Text, "Text should be handled by GetTextFollowing in order to take into account collapsed text."); Debug.Assert(page[idx].NodeType != XPathNodeType.Attribute, "Current node should never be an attribute or namespace--caller should handle this case."); // Since nodes are laid out in document order on pages, scan them sequentially // rather than following sibling/child/parent links. idx++; do { if ((object)page == (object)pageEnd && idx <= idxEnd) { // Only scan to termination point while (idx != idxEnd) { if (((1 << (int)page[idx].NodeType) & mask) != 0) { goto FoundNode; } idx++; } break; } else { // Scan all nodes in the page while (idx < page[0].PageInfo.NodeCount) { if (((1 << (int)page[idx].NodeType) & mask) != 0) { goto FoundNode; } idx++; } } page = page[0].PageInfo.NextPage; idx = 1; }while (page != null); return(false); FoundNode: Debug.Assert(!page[idx].IsAttrNmsp, "GetContentFollowing should never return attributes or namespaces."); // Found match pageCurrent = page; idxCurrent = idx; return(true); }
public static bool GetPreviousContentSibling(ref XPathNode[] pageNode, ref int idxNode, XPathNodeType typ) { XPathNode[] nodeArray = pageNode; int index = idxNode; int contentKindMask = XPathNavigator.GetContentKindMask(typ); do { if (!GetPreviousContentSibling(ref nodeArray, ref index)) { return(false); } }while (((((int)1) << nodeArray[index].NodeType) & contentKindMask) == 0); pageNode = nodeArray; idxNode = index; return(true); }
public static bool GetContentFollowing(ref XPathNode[] pageCurrent, ref int idxCurrent, XPathNode[] pageEnd, int idxEnd, XPathNodeType typ) { XPathNode[] nextPage = pageCurrent; int index = idxCurrent; int contentKindMask = XPathNavigator.GetContentKindMask(typ); index++; Label_0012: if ((nextPage != pageEnd) || (index > idxEnd)) { while (index < nextPage[0].PageInfo.NodeCount) { if (((((int)1) << nextPage[index].NodeType) & contentKindMask) != 0) { goto Label_0081; } index++; } nextPage = nextPage[0].PageInfo.NextPage; index = 1; if (nextPage != null) { goto Label_0012; } } else { while (index != idxEnd) { if (((((int)1) << nextPage[index].NodeType) & contentKindMask) != 0) { goto Label_0081; } index++; } } return(false); Label_0081: pageCurrent = nextPage; idxCurrent = index; return(true); }
public static bool GetContentSibling(ref XPathNode[] pageNode, ref int idxNode, XPathNodeType typ) { XPathNode[] nodeArray = pageNode; int index = idxNode; int contentKindMask = XPathNavigator.GetContentKindMask(typ); if (nodeArray[index].NodeType != XPathNodeType.Attribute) { do { index = nodeArray[index].GetSibling(out nodeArray); if (index == 0) { goto Label_004B; } }while (((((int)1) << nodeArray[index].NodeType) & contentKindMask) == 0); pageNode = nodeArray; idxNode = index; return(true); } Label_004B: return(false); }
/// <summary> /// Keep only nodes with XPathNodeType = nodeType, where XPathNodeType.Text selects whitespace as well. /// </summary> private XmlNavTypeFilter(XPathNodeType nodeType) { Debug.Assert(nodeType != XPathNodeType.Attribute && nodeType != XPathNodeType.Namespace); this.nodeType = nodeType; this.mask = XPathNavigator.GetContentKindMask(nodeType); }
public bool IsContentKindMatch(XPathNodeType typ) { return(((((int)1) << this.pageCurrent[this.idxCurrent].NodeType) & XPathNavigator.GetContentKindMask(typ)) != 0); }