/*================================================================
*   ixmlNode_insertBefore
*       Inserts the node newChild before the existing child node refChild.
*       If refChild is null, insert newChild at the end of the list of
*       children. If the newChild is already in the tree, it is first
*       removed.   
*       External function.
*   Parameters:
*       newChild: the node to insert.
*   Returns:
*
*=================================================================*/
int
ixmlNode_insertBefore( IN IXML_Node * nodeptr,
                       IN IXML_Node * newChild,
                       IN IXML_Node * refChild )
{

    int ret = IXML_SUCCESS;

    if( ( nodeptr == NULL ) || ( newChild == NULL ) ) {
        return IXML_INVALID_PARAMETER;
    }
    // whether nodeptr allow children of the type of newChild 
    if( ixmlNode_allowChildren( nodeptr, newChild ) == FALSE ) {
        return IXML_HIERARCHY_REQUEST_ERR;
    }
    // or if newChild is one of nodeptr's ancestors
    if( ixmlNode_isAncestor( newChild, nodeptr ) == TRUE ) {
        return IXML_HIERARCHY_REQUEST_ERR;
    }
    // if newChild was created from a different document 
    if( nodeptr->ownerDocument != newChild->ownerDocument ) {
        return IXML_WRONG_DOCUMENT_ERR;
    }
    // if refChild is not a child of nodeptr
    if( ixmlNode_isParent( nodeptr, refChild ) == FALSE ) {
        return IXML_NOT_FOUND_ERR;
    }

    if( refChild != NULL ) {
        if( ixmlNode_isParent( nodeptr, newChild ) == TRUE ) {
            ixmlNode_removeChild( nodeptr, newChild, NULL );
            newChild->nextSibling = NULL;
            newChild->prevSibling = NULL;
        }

        newChild->nextSibling = refChild;
        if( refChild->prevSibling != NULL ) {
            ( refChild->prevSibling )->nextSibling = newChild;
            newChild->prevSibling = refChild->prevSibling;
        }

        refChild->prevSibling = newChild;

        if( newChild->prevSibling == NULL ) {
            nodeptr->firstChild = newChild;
        }

        newChild->parentNode = nodeptr;

    } else {
        ret = ixmlNode_appendChild( nodeptr, newChild );
    }

    return ret;
}
/*================================================================
*   ixmlNode_isAncestor
*       check if ancestorNode is ancestor of toFind 
*       Internal to parser only.
*   Returns:
*       TRUE or FALSE
*
*=================================================================*/
BOOL
ixmlNode_isAncestor( IXML_Node * ancestorNode,
                     IXML_Node * toFind )
{

    BOOL found = FALSE;

    if( ( ancestorNode != NULL ) && ( toFind != NULL ) ) {
        if( toFind->parentNode == ancestorNode ) {
            return TRUE;
        } else {
            found =
                ixmlNode_isAncestor( ancestorNode->firstChild, toFind );
            if( found == FALSE ) {
                found =
                    ixmlNode_isAncestor( ancestorNode->nextSibling,
                                         toFind );
            }
        }
    }

    return found;
}
示例#3
0
文件: node.c 项目: rxwen/pupnp
/*!
 * \brief Check if ancestorNode is ancestor of toFind.
 *
 * \return TRUE or FALSE.
 */
static BOOL ixmlNode_isAncestor(
    /*! [in] The candidate to ancestor \b Node. */
    IXML_Node *ancestorNode,
    /*! [in] The \b Node to check for an ancestor. */
    IXML_Node *toFind)
{
    BOOL found = FALSE;

    if (ancestorNode != NULL && toFind != NULL) {
        if (toFind->parentNode == ancestorNode) {
            return TRUE;
        } else {
            found = ixmlNode_isAncestor(
                        ancestorNode->firstChild, toFind);
            if (found == FALSE) {
                found = ixmlNode_isAncestor(
                            ancestorNode->nextSibling, toFind);
            }
        }
    }

    return found;
}
/*=============================================================================
*   ixmlNode_appendChild
*       Adds the node newChild to the end of the list of children of this node.
*       If the newChild is already in the tree, it is first removed.
*       External function.   
*   Parameter:
*       newChild: the node to add.
*   Return Value:
*       IXML_SUCCESS
*       IXML_INVALID_PARAMETER:     if either nodeptr or newChild is NULL
*       IXML_WRONG_DOCUMENT_ERR:    if newChild was created from a different document than
*                                   the one that created nodeptr.
*       IXML_HIERARCHY_REQUEST_ERR: if newChild is ancestor of nodeptr or if nodeptr is of
*                                   a type that does not allow children of the type of the
*                                   newChild node.
*
*=================================================================*/
int
ixmlNode_appendChild( IN IXML_Node * nodeptr,
                      IN IXML_Node * newChild )
{

    IXML_Node *prev = NULL,
     *next = NULL;

    if( ( nodeptr == NULL ) || ( newChild == NULL ) ) {
        return IXML_INVALID_PARAMETER;
    }
    // if newChild was created from a different document 
    if( ( newChild->ownerDocument != NULL ) &&
        ( nodeptr->ownerDocument != newChild->ownerDocument ) ) {
        return IXML_WRONG_DOCUMENT_ERR;
    }
    // if newChild is an ancestor of nodeptr
    if( ixmlNode_isAncestor( newChild, nodeptr ) == TRUE ) {
        return IXML_HIERARCHY_REQUEST_ERR;
    }
    // if nodeptr does not allow to have newChild as children
    if( ixmlNode_allowChildren( nodeptr, newChild ) == FALSE ) {
        return IXML_HIERARCHY_REQUEST_ERR;
    }

    if( ixmlNode_isParent( nodeptr, newChild ) == TRUE ) {
        ixmlNode_removeChild( nodeptr, newChild, NULL );
    }
    // set the parent node pointer
    newChild->parentNode = nodeptr;
    newChild->ownerDocument = nodeptr->ownerDocument;

    //if the first child
    if( nodeptr->firstChild == NULL ) {
        nodeptr->firstChild = newChild;
    } else {
        prev = nodeptr->firstChild;
        next = prev->nextSibling;
        while( next != NULL ) {
            prev = next;
            next = prev->nextSibling;
        }
        prev->nextSibling = newChild;
        newChild->prevSibling = prev;
    }

    return IXML_SUCCESS;
}
/*================================================================
*   ixmlNode_replaceChild
*       Replaces the child node oldChild with newChild in the list of children,
*       and returns the oldChild node.
*       External function.
*   Parameters:
*       newChild:   the new node to put in the child list.
*       oldChild:   the node being replaced in the list.
*       returnNode: the node replaced.
*   Return Value:
*       IXML_SUCCESS
*       IXML_INVALID_PARAMETER:     if anyone of nodeptr, newChild or oldChild is NULL.
*       IXML_HIERARCHY_REQUEST_ERR: if the newChild is ancestor of nodeptr or nodeptr
*                                   is of a type that does not allow children of the
*                                   type of the newChild node.
*       IXML_WRONG_DOCUMENT_ERR:    if newChild was created from a different document than
*                                   the one that created this node.
*       IXML_NOT_FOUND_ERR:         if oldChild is not a child of nodeptr.
*
*=================================================================*/
int
ixmlNode_replaceChild( IN IXML_Node * nodeptr,
                       IN IXML_Node * newChild,
                       IN IXML_Node * oldChild,
                       OUT IXML_Node ** returnNode )
{
    int ret = IXML_SUCCESS;

    if( ( nodeptr == NULL ) || ( newChild == NULL )
        || ( oldChild == NULL ) ) {
        return IXML_INVALID_PARAMETER;
    }
    // if nodetype of nodeptr does not allow children of the type of newChild 
    // needs to add later

    // or if newChild is one of nodeptr's ancestors
    if( ixmlNode_isAncestor( newChild, nodeptr ) == TRUE ) {
        return IXML_HIERARCHY_REQUEST_ERR;
    }

    if( ixmlNode_allowChildren( nodeptr, newChild ) == FALSE ) {
        return IXML_HIERARCHY_REQUEST_ERR;
    }
    // if newChild was created from a different document 
    if( nodeptr->ownerDocument != newChild->ownerDocument ) {
        return IXML_WRONG_DOCUMENT_ERR;
    }
    // if refChild is not a child of nodeptr
    if( ixmlNode_isParent( nodeptr, oldChild ) != TRUE ) {
        return IXML_NOT_FOUND_ERR;
    }

    ret = ixmlNode_insertBefore( nodeptr, newChild, oldChild );
    if( ret != IXML_SUCCESS ) {
        return ret;
    }

    ret = ixmlNode_removeChild( nodeptr, oldChild, returnNode );
    return ret;
}