rangeimpl.cpp

来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,660 行 · 第 1/4 页

CPP
1,660
字号
        return;    }    DOM_Node parent = refNode.getParentNode();    if (parent != null ) // REVIST: what to do if it IS null?    {        fStartContainer = parent;        fEndContainer = parent;        unsigned int i = 0;        for (DOM_Node n = parent.getFirstChild(); n!=null, n!=refNode; n = n.getNextSibling()) {            i++;        }        fStartOffset = i;        fEndOffset = fStartOffset+1;    }}void RangeImpl::selectNodeContents(const DOM_Node& node){    validateNode(node);    fStartContainer = node;    fEndContainer = node;    fStartOffset = 0;    if (node.getNodeType() == DOM_Node::TEXT_NODE ) {        fEndOffset = ((DOM_Text &)node).getLength();        return;    }    DOM_Node first = node.getFirstChild();    if (first == null) {        fEndOffset = 0;        return;    }    unsigned int i = 0;    for (DOM_Node n = first; n!=null; n = n.getNextSibling()) {        i++;    }    fEndOffset = i;}void RangeImpl::surroundContents(DOM_Node& newParent){    if (newParent==null) return;    //check for elimination criteria    if( fDetached) {        throw DOM_DOMException(            DOM_DOMException::INVALID_STATE_ERR, null);    }    if (newParent.getOwnerDocument() !=fDocument) {        throw DOM_DOMException(            DOM_DOMException::WRONG_DOCUMENT_ERR, null);    }    int type = newParent.getNodeType();    if ( !isLegalContainedNode(newParent)        || type == DOM_Node::DOCUMENT_TYPE_NODE)    {        throw DOM_RangeException(            DOM_RangeException::INVALID_NODE_TYPE_ERR, null);    }    DOM_Node root = getCommonAncestorContainer();    DOM_Node realStart = fStartContainer;    DOM_Node realEnd = fEndContainer;    if (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) {        realStart = fStartContainer.getParentNode();    }    if (fEndContainer.getNodeType() == DOM_Node::TEXT_NODE) {        realEnd = fEndContainer.getParentNode();    }    if (realStart != realEnd) {        throw DOM_RangeException(            DOM_RangeException::BAD_BOUNDARYPOINTS_ERR, null);    }    DOM_DocumentFragment frag = extractContents();    insertNode(newParent);    newParent.appendChild(frag);    selectNode(newParent);}short RangeImpl::compareBoundaryPoints(DOM_Range::CompareHow how, RangeImpl* srcRange) const{    if (fDocument != srcRange->fDocument) {        throw DOM_DOMException(            DOM_DOMException::WRONG_DOCUMENT_ERR, null);    }    if( fDetached) {        throw DOM_DOMException(            DOM_DOMException::INVALID_STATE_ERR, null);    }    DOM_Node pointA, pointB;    int offsetA, offsetB;    switch (how)    {    case (DOM_Range::START_TO_START) :        pointB = srcRange->getStartContainer();        pointA = fStartContainer;        offsetB = srcRange->getStartOffset();        offsetA = fStartOffset;        break;    case (DOM_Range::START_TO_END) :        pointB = srcRange->getStartContainer();        pointA = fEndContainer;        offsetB = srcRange->getStartOffset();        offsetA = fEndOffset;        break;    case (DOM_Range::END_TO_START) :        pointB = srcRange->getEndContainer();        pointA = fStartContainer;        offsetB = srcRange->getEndOffset();        offsetA = fStartOffset;        break;    case (DOM_Range::END_TO_END) :        pointB = srcRange->getEndContainer();        pointA = fEndContainer;        offsetB = srcRange->getEndOffset();        offsetA = fEndOffset;        break;    }    // case 1: same container    if (pointA == pointB) {        if (offsetA < offsetB) return -1; //A before B        if (offsetA == offsetB) return 0; //A equal to B        return 1; // A after B    }    // case 2: Child C of container A is ancestor of B    for (DOM_Node node = pointA.getFirstChild(); node != null; node=node.getNextSibling()) {        if (isAncestorOf(node, pointB)) {            int index = indexOf(node, pointA);            if (offsetA <=  index) return -1;            return 1;        }    }    // case 3: Child C of container B is ancestor of A    for (DOM_Node nd = pointB.getFirstChild(); nd != null; nd=nd.getNextSibling()) {        if (isAncestorOf(nd, pointA)) {            int index = indexOf(nd, pointB);            if (index < offsetB ) return -1;            return 1; //B strictly before A        }    }    // case 4: preorder traversal of context tree.    DOM_Node ancestor = commonAncestorOf(pointA, pointB);    DOM_Node current = ancestor;    do {        if (current == pointA) return -1;        if (current == pointB) return 1;        current = nextNode(current, true);    }    while (current!=null && current!=ancestor);    return -2; // this should never happen}void RangeImpl:: deleteContents(){    traverseContents(DELETE_CONTENTS);}DOM_DocumentFragment RangeImpl::extractContents(){    checkReadOnly(fStartContainer, fEndContainer, fStartOffset, fEndOffset);    return traverseContents(EXTRACT_CONTENTS);}DOM_DocumentFragment RangeImpl::cloneContents() const{    // cast off const.    return ((RangeImpl *)this)->traverseContents(CLONE_CONTENTS);}void RangeImpl::insertNode(DOM_Node& newNode){    if (newNode == null) return; //don't have to do anything    for (DOM_Node aNode = fStartContainer; aNode!=null; aNode = aNode.getParentNode()) {        if (aNode.fImpl->isReadOnly()) {        throw DOM_DOMException(            DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null);    }    }    if (fDocument != newNode.getOwnerDocument()) {        throw DOM_DOMException(            DOM_DOMException::WRONG_DOCUMENT_ERR, null);    }    // Prevent cycles in the tree.    //isKidOK() is not checked here as its taken care by insertBefore() function    if (isAncestorOf( newNode, fStartContainer)) {        throw DOM_DOMException(            DOM_DOMException::HIERARCHY_REQUEST_ERR, null);    }    if( fDetached) {        throw DOM_DOMException(            DOM_DOMException::INVALID_STATE_ERR, null);    }    int type = newNode.getNodeType();    if (type == DOM_Node::ATTRIBUTE_NODE        || type == DOM_Node::ENTITY_NODE        || type == DOM_Node::NOTATION_NODE        || type == DOM_Node::DOCUMENT_NODE)    {        throw DOM_RangeException(            DOM_RangeException::INVALID_NODE_TYPE_ERR, null);    }    DOM_Node parent;    DOM_Node next;    if (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) {        //set 'parent' and 'next' here        parent = fStartContainer.getParentNode();        //split the text nodes       if (fStartOffset > 0)            ((DOM_Text &)fStartContainer).splitText(fStartOffset);        //update the new start information later. After inserting the first newNode        if (fStartOffset == 0)            next = fStartContainer;        else            next = fStartContainer.getNextSibling();    } // end of text handling    else {        parent = fStartContainer;        next = fStartContainer.getFirstChild();        for(unsigned int i = 0; (i < fStartOffset) && (next != null); i++) {            next=next.getNextSibling();        }    }    if (parent != null) {        if (next != null)            parent.insertBefore(newNode, next);        else            parent.appendChild(newNode);    }}RangeImpl* RangeImpl::cloneRange() const{    if( fDetached) {        throw DOM_DOMException(            DOM_DOMException::INVALID_STATE_ERR, null);    }    RangeImpl* range = ((DocumentImpl*)fDocument.fImpl)->createRange();    range->setStart(fStartContainer, fStartOffset);    range->setEnd(fEndContainer, fEndOffset);    return range;}DOMString RangeImpl::toString() const{    if( fDetached) {        throw DOM_DOMException(            DOM_DOMException::INVALID_STATE_ERR, null);    }    DOM_Node node = fStartContainer;    DOM_Node stopNode = fEndContainer;    DOMString tempString;    if ( (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE)        || (fStartContainer.getNodeType() == DOM_Node::CDATA_SECTION_NODE) ) {        if (fStartContainer == fEndContainer) {            tempString.appendData(fStartContainer.getNodeValue().substringData(fStartOffset, fEndOffset-fStartOffset));            return tempString;        } else {            int length = fStartContainer.getNodeValue().length();            tempString.appendData(fStartContainer.getNodeValue().substringData(fStartOffset, length - fStartOffset));            node = nextNode(node, true);        }    }else { //fStartContainer is not a TextNode        node=node.getFirstChild();        if (fStartOffset>0) { //find a first node within a range, specified by fStartOffset            unsigned int counter = 0;            while (counter<fStartOffset && node!=null) {                node=node.getNextSibling();                counter++;            }        }        if (node == null) {            node = nextNode(fStartContainer,false);        }    }    if ( fEndContainer.getNodeType()!= DOM_Node::TEXT_NODE &&        fEndContainer.getNodeType()!= DOM_Node::CDATA_SECTION_NODE ){        int i=fEndOffset;        stopNode = fEndContainer.getFirstChild();        while( i>0 && stopNode!=null ){            --i;            stopNode = stopNode.getNextSibling();        }        if ( stopNode == null )            stopNode = nextNode( fEndContainer, false );    }    while (node != stopNode) {  //look into all kids of the Range        if (node == null) break;        if (node.getNodeType() == DOM_Node::TEXT_NODE            ||  node.getNodeType() == DOM_Node::CDATA_SECTION_NODE) {            tempString.appendData(node.getNodeValue());        }        node = nextNode(node, true);    }    if (fEndContainer.getNodeType() == DOM_Node::TEXT_NODE        || fEndContainer.getNodeType() == DOM_Node::CDATA_SECTION_NODE) {        tempString.appendData(fEndContainer.getNodeValue().substringData(0,fEndOffset));    }    return tempString;}DOM_Document RangeImpl::getDocument(){    return fDocument;}const DOM_Node RangeImpl::getCommonAncestorContainer() const{     return commonAncestorOf(fStartContainer, fEndContainer);}//---------------------//private functions//---------------------bool RangeImpl::isValidAncestorType(const DOM_Node& node) const{    for (DOM_Node aNode = node; aNode!=null; aNode = aNode.getParentNode()) {        short type = aNode.getNodeType();        if ( type == DOM_Node::ENTITY_NODE            || type == DOM_Node::NOTATION_NODE            || type == DOM_Node::DOCUMENT_TYPE_NODE)            return false;    }    return true;}bool RangeImpl::isAncestorOf(const DOM_Node& a, const DOM_Node& b) {    for (DOM_Node node=b; node != null; node=node.getParentNode()) {        if  (node == a) return true;    }    return false;}bool RangeImpl::hasLegalRootContainer(const DOM_Node& node) const {    if ( node==null )        return false;    DOM_Node rootContainer = node;    for (; rootContainer.getParentNode()!=null; rootContainer = rootContainer.getParentNode())        ;    switch( rootContainer.getNodeType() ) {        case DOM_Node::ATTRIBUTE_NODE:        case DOM_Node::DOCUMENT_NODE:        case DOM_Node::DOCUMENT_FRAGMENT_NODE:        return true;    }    return false;}bool RangeImpl::isLegalContainedNode(const DOM_Node& node ) const {   if ( node==null )       return false;   switch( node.getNodeType() )   {       case DOM_Node::DOCUMENT_NODE:       case DOM_Node::DOCUMENT_FRAGMENT_NODE:       case DOM_Node::ATTRIBUTE_NODE:       case DOM_Node::ENTITY_NODE:       case DOM_Node::NOTATION_NODE:       return false;   }   return true;}unsigned short RangeImpl::indexOf(const DOM_Node& child, const DOM_Node& parent) const{    unsigned short i = 0;    if (child.getParentNode() != parent) return (unsigned short)-1;    for(DOM_Node node = child.getPreviousSibling(); node!= null; node=node.getPreviousSibling()) {        i++;    }    return i;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?