domrangeimpl.cpp

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

CPP
2,115
字号
void DOMRangeImpl::detach(){    if( fDetached) {        throw DOMException(            DOMException::INVALID_STATE_ERR, 0, fMemoryManager);    }    ((DOMDocumentImpl *)fDocument)->removeRange(this);    fDetached = true;    //0ify nodes    fStartContainer = 0;    fStartOffset    = 0;    fEndContainer   = 0;    fEndOffset      = 0;    fCollapsed      = true;    fRemoveChild    = 0;}void DOMRangeImpl::collapse(bool toStart){    if( fDetached) {        throw DOMException(            DOMException::INVALID_STATE_ERR, 0, fMemoryManager);    }    if (toStart) {        fEndContainer = fStartContainer;        fEndOffset = fStartOffset;    } else {        fStartContainer = fEndContainer;        fStartOffset = fEndOffset;    }    fCollapsed = true;}void DOMRangeImpl::selectNode(const DOMNode* refNode){    validateNode(refNode);    if ( !isLegalContainedNode(refNode)) {        throw DOMRangeException(            DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager);    }    //First check for the text type node    short type = refNode->getNodeType();    if((type == DOMNode::TEXT_NODE        || type == DOMNode::CDATA_SECTION_NODE        || type == DOMNode::COMMENT_NODE        || type == DOMNode::PROCESSING_INSTRUCTION_NODE))    {        //The node itself is the container.        fStartContainer = (DOMNode*) refNode;        fEndContainer   = (DOMNode*) refNode;        //Select all the contents of the node        fStartOffset = 0;        if (type == DOMNode::PROCESSING_INSTRUCTION_NODE)            fEndOffset = XMLString::stringLen(((DOMProcessingInstruction*)refNode)->getData());        else            fEndOffset = ((DOMText *)refNode)->getLength();        return;    }    DOMNode* parent = refNode->getParentNode();    if (parent != 0 ) // REVIST: what to do if it IS 0?    {        fStartContainer = parent;        fEndContainer = parent;        XMLSize_t i = 0;        for (DOMNode* n = parent->getFirstChild(); n!=0 && n!=refNode; n = n->getNextSibling()) {            i++;        }        fStartOffset = i;        fEndOffset = fStartOffset+1;    }}void DOMRangeImpl::selectNodeContents(const DOMNode* node){    validateNode(node);    fStartContainer = (DOMNode*) node;    fEndContainer = (DOMNode*) node;    fStartOffset = 0;    short type = node->getNodeType();    if((type == DOMNode::TEXT_NODE        || type == DOMNode::CDATA_SECTION_NODE        || type == DOMNode::COMMENT_NODE)) {        fEndOffset = ((DOMText *)node)->getLength();        return;    }    if (type == DOMNode::PROCESSING_INSTRUCTION_NODE) {        fEndOffset = XMLString::stringLen(((DOMProcessingInstruction*)node)->getData());        return;    }    DOMNode* first = node->getFirstChild();    if (first == 0) {        fEndOffset = 0;        return;    }    XMLSize_t i = 0;    for (DOMNode* n = first; n!=0; n = n->getNextSibling()) {        i++;    }    fEndOffset = i;}void DOMRangeImpl::surroundContents(DOMNode* newParent){    if (newParent==0) return;    //check for elimination criteria    if( fDetached) {        throw DOMException(            DOMException::INVALID_STATE_ERR, 0, fMemoryManager);    }    if (newParent->getOwnerDocument() !=fDocument) {        throw DOMException(            DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager);    }    int type = newParent->getNodeType();    if ( !isLegalContainedNode(newParent)        || type == DOMNode::DOCUMENT_TYPE_NODE)    {        throw DOMRangeException(            DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager);    }    DOMNode* realStart = fStartContainer;    DOMNode* realEnd = fEndContainer;    type = fStartContainer->getNodeType();    if((type == DOMNode::TEXT_NODE        || type == DOMNode::CDATA_SECTION_NODE        || type == DOMNode::COMMENT_NODE        || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) {        realStart = fStartContainer->getParentNode();    }    type = fEndContainer->getNodeType();    if((type == DOMNode::TEXT_NODE        || type == DOMNode::CDATA_SECTION_NODE        || type == DOMNode::COMMENT_NODE        || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) {        realEnd = fEndContainer->getParentNode();    }    if (realStart != realEnd) {        throw DOMRangeException(            DOMRangeException::BAD_BOUNDARYPOINTS_ERR, 0, fMemoryManager);    }    DOMDocumentFragment* frag = (DOMDocumentFragment*) extractContents();    insertNode(newParent);    newParent->appendChild(frag);    selectNode(newParent);}short DOMRangeImpl::compareBoundaryPoints(DOMRange::CompareHow how, const DOMRange* srcRange) const{    if (fDocument != ((DOMRangeImpl*)srcRange)->fDocument) {        throw DOMException(            DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager);    }    if( fDetached) {        throw DOMException(            DOMException::INVALID_STATE_ERR, 0, fMemoryManager);    }    DOMNode* pointA;    DOMNode* pointB;    int offsetA, offsetB;    switch (how)    {    case (DOMRange::START_TO_START) :        pointB = srcRange->getStartContainer();        pointA = fStartContainer;        offsetB = srcRange->getStartOffset();        offsetA = fStartOffset;        break;    case (DOMRange::START_TO_END) :        pointB = srcRange->getStartContainer();        pointA = fEndContainer;        offsetB = srcRange->getStartOffset();        offsetA = fEndOffset;        break;    case (DOMRange::END_TO_START) :        pointB = srcRange->getEndContainer();        pointA = fStartContainer;        offsetB = srcRange->getEndOffset();        offsetA = fStartOffset;        break;    case (DOMRange::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 (DOMNode* node = pointA->getFirstChild(); node != 0; 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 (DOMNode* nd = pointB->getFirstChild(); nd != 0; 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.    // Instead of literally walking the context tree in pre-order,    // we use relative node depth walking which is usually faster    int depthDiff = 0;    DOMNode* n = 0;    for ( n = pointB; n != 0; n = n->getParentNode() )        depthDiff++;    for ( n = pointA; n != 0; n = n->getParentNode() )        depthDiff--;    while (depthDiff > 0) {        pointB = pointB->getParentNode();        depthDiff--;    }    while (depthDiff < 0) {        pointA = pointA->getParentNode();        depthDiff++;    }    for (DOMNode* pB = pointB->getParentNode(),         *pA = pointA->getParentNode();         pB != pA;         pB = pB->getParentNode(), pA = pA->getParentNode() )    {        pointB = pB;        pointA = pA;    }    for ( n = pointB->getNextSibling();         n != 0;         n = n->getNextSibling() )    {        if (n == pointA) {            return 1;        }    }    return -1;}void DOMRangeImpl:: deleteContents(){    traverseContents(DELETE_CONTENTS);}DOMDocumentFragment* DOMRangeImpl::extractContents(){    checkReadOnly(fStartContainer, fEndContainer, fStartOffset, fEndOffset);    return traverseContents(EXTRACT_CONTENTS);}DOMDocumentFragment* DOMRangeImpl::cloneContents() const{    // cast off const.    return ((DOMRangeImpl *)this)->traverseContents(CLONE_CONTENTS);}void DOMRangeImpl::insertNode(DOMNode* newNode){    if (newNode == 0) return; //don't have to do anything    if( fDetached) {        throw DOMException(            DOMException::INVALID_STATE_ERR, 0, fMemoryManager);    }    int type = newNode->getNodeType();    if (type == DOMNode::ATTRIBUTE_NODE        || type == DOMNode::ENTITY_NODE        || type == DOMNode::NOTATION_NODE        || type == DOMNode::DOCUMENT_NODE)    {        throw DOMRangeException(            DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager);    }    // Prevent cycles in the tree.    //isKidOK() is not checked here as its taken care by insertBefore() function    if (isAncestorOf( newNode, fStartContainer)) {        throw DOMException(            DOMException::HIERARCHY_REQUEST_ERR, 0, fMemoryManager);    }    for (DOMNode* aNode = fStartContainer; aNode!=0; aNode = aNode->getParentNode()) {        if (castToNodeImpl(newNode)->isReadOnly()) {        throw DOMException(            DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, fMemoryManager);    }    }    if (fDocument != newNode->getOwnerDocument()) {        throw DOMException(            DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager);    }    DOMNode* parent;    DOMNode* next;    type = fStartContainer->getNodeType();    if((type == DOMNode::TEXT_NODE        || type == DOMNode::CDATA_SECTION_NODE        || type == DOMNode::COMMENT_NODE        || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) {        //set 'parent' and 'next' here        parent = fStartContainer->getParentNode();        //split the text nodes       if (fStartOffset > 0) {           if (type == DOMNode::COMMENT_NODE)               ((DOMCommentImpl*)fStartContainer)->splitText(fStartOffset);           else if (type == DOMNode::PROCESSING_INSTRUCTION_NODE)               ((DOMProcessingInstructionImpl*)fStartContainer)->splitText(fStartOffset);           else               ((DOMText*)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(XMLSize_t i = 0; (i < fStartOffset) && (next != 0); i++) {            next=next->getNextSibling();        }    }    if (parent != 0) {        if (next != 0)            parent->insertBefore(newNode, next);        else            parent->appendChild(newNode);    }}DOMRange* DOMRangeImpl::cloneRange() const{    if( fDetached) {        throw DOMException(            DOMException::INVALID_STATE_ERR, 0, fMemoryManager);    }    DOMRange* range = fDocument->createRange();    range->setStart(fStartContainer, fStartOffset);    range->setEnd(fEndContainer, fEndOffset);    return range;}const XMLCh* DOMRangeImpl::toString() const{    if( fDetached) {        throw DOMException(            DOMException::INVALID_STATE_ERR, 0, fMemoryManager);    }    if ((fStartContainer == fEndContainer) && (fEndOffset == fStartOffset))        return XMLUni::fgZeroLenString;    DOMNode* node = fStartContainer;    DOMNode* stopNode = fEndContainer;    XMLBuffer retStringBuf(1023, ((DOMDocumentImpl *)fDocument)->getMemoryManager());    short type = fStartContainer->getNodeType();    if((type == DOMNode::TEXT_NODE        || type == DOMNode::CDATA_SECTION_NODE        || type == DOMNode::COMMENT_NODE        || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) {        if (fStartContainer == fEndContainer) {            XMLCh* tempString;            XMLCh temp[4000];            if ((fEndOffset-fStartOffset) >= 3999)                tempString = (XMLCh*) fMemoryManager->allocate                (                    (fEndOffset - fStartOffset + 1) * sizeof(XMLCh)                );//new XMLCh[fEndOffset-fStartOffset+1];            else                tempString = temp;            XMLString::subString(tempString, fStartContainer->getNodeValue(), fStartOffset, fEndOffset, ((DOMDocumentImpl *)fDocument)->getMemoryManager());            const XMLCh* retString = ((DOMDocumentImpl *)fDocument)->getPooledString(tempString);            if ((fEndOffset-fStartOffset) >= 3999)

⌨️ 快捷键说明

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