⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ixmlparser.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 5 页
字号:

/*==============================================================================*
*   Parser_UTF8ToInt
*       In UTF-8, characters are encoded using sequences of 1 to 6 octets.
*       This functions will return a UTF-8 character value and its octets number.
*       Internal to parser only.
*       Internal to parser only
*          
*===============================================================================*/
static int
Parser_UTF8ToInt( IN char *ss,
                  OUT int *len )
{

    unsigned char *s = ( unsigned char * )ss;
    int c = *s;

    if( c <= 127 ) {            // if c<=127, c is just the character.
        *len = 1;
        return c;
    } else if( ( c & 0xE0 ) == 0xC0 && ( s[1] & 0xc0 ) == 0x80 ) {  // a sequence of 110xxxxx and 10xxxxxx?
        *len = 2;
        return ( ( ( c & 0x1f ) << 6 ) | ( s[1] & 0x3f ) );
    } else if( ( c & 0xF0 ) == 0xE0 && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 ) {   // a sequence of 1110xxxx,10xxxxxx and 10xxxxxx ?
        *len = 3;
        return ( ( ( c & 0xf ) << 12 ) | ( ( s[1] & 0x3f ) << 6 ) |
                 ( s[2] & 0x3f ) );
    } else if( ( c & 0xf8 ) == 0xf0 && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 && ( s[3] & 0xc0 ) == 0x80 ) {    // a sequence of 11110xxx,10xxxxxx,10xxxxxx and 10xxxxxx ?
        *len = 4;
        return ( ( ( c & 0x7 ) << 18 ) | ( ( s[1] & 0x3f ) << 12 ) |
                 ( ( s[2] & 0x3f ) << 6 ) | ( s[3] & 0x3f ) );
    } else if( ( c & 0xfc ) == 0xf8 && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 && ( s[3] & 0xc0 ) == 0x80 && ( s[4] & 0xc0 ) == 0x80 ) { // a sequence of 111110xx,10xxxxxx,10xxxxxx,10xxxxxx,10xxxxxx ?
        *len = 5;
        return ( ( ( c & 0x3 ) << 24 ) | ( ( s[1] & 0x3f ) << 18 ) |
                 ( ( s[2] & 0x3f ) << 12 ) | ( ( s[3] & 0x3f ) << 6 ) |
                 ( s[4] & 0x3f ) );
    } else if( ( c & 0xfe ) == 0xfc && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 && ( s[3] & 0xc0 ) == 0x80 && ( s[4] & 0xc0 ) == 0x80 && ( s[5] & 0xc0 ) == 0x80 ) {  // a sequence of 1111110x,10xxxxxx,10xxxxxx,10xxxxxx,10xxxxxx and 10xxxxxx ?
        *len = 6;
        return ( ( ( c & 0x1 ) << 30 ) | ( ( s[1] & 0x3f ) << 24 ) |
                 ( ( s[2] & 0x3f ) << 18 ) | ( ( s[3] & 0x3f ) << 12 ) |
                 ( ( s[4] & 0x3f ) << 6 ) | ( s[5] & 0x3f ) );
    } else {                    // none of above, error
        *len = 0;
        return -1;
    }
}

/*==============================================================================*
*   Parser_init
*       Initializes a xml parser.
*       Internal to parser only
*			
*===============================================================================*/
static Parser *
Parser_init(  )
{
    Parser *newParser = NULL;

    newParser = ( Parser * ) malloc( sizeof( Parser ) );
    if( newParser == NULL ) {
        return NULL;
    }

    memset( newParser, 0, sizeof( Parser ) );

    ixml_membuf_init( &( newParser->tokenBuf ) );
    ixml_membuf_init( &( newParser->lastElem ) );

    return newParser;
}

/*================================================================
*   Parser_isValidEndElement
*       check if a new node->nodeName matches top of element stack.
*       Internal to parser only.
*
*=================================================================*/
static int
Parser_isValidEndElement( IN Parser * xmlParser,
                          IN IXML_Node * newNode )
{
    return ( strcmp( xmlParser->pCurElement->element, newNode->nodeName )
             == 0 );
}

/*===============================================================
*   Parser_pushElement
*       push a new element onto element stack
*       Internal to parser only.
*
*=================================================================*/
static int
Parser_pushElement( IN Parser * xmlParser,
                    IN IXML_Node * newElement )
{

    IXML_ElementStack *pCurElement = NULL;
    IXML_ElementStack *pNewStackElement = NULL;

    assert( newElement );
    if( newElement != NULL ) {
        // push new element
        pNewStackElement =
            ( IXML_ElementStack * ) malloc( sizeof( IXML_ElementStack ) );
        if( pNewStackElement == NULL ) {
            return IXML_INSUFFICIENT_MEMORY;
        }

        memset( pNewStackElement, 0, sizeof( IXML_ElementStack ) );
        // the element member includes both prefix and name 

        pNewStackElement->element = strdup( newElement->nodeName );
        if( pNewStackElement->element == NULL ) {
            free( pNewStackElement );
            return IXML_INSUFFICIENT_MEMORY;
        }

        if( newElement->prefix != 0 ) {
            pNewStackElement->prefix = strdup( newElement->prefix );
            if( pNewStackElement->prefix == NULL ) {
                Parser_freeElementStackItem( pNewStackElement );
                free( pNewStackElement );
                return IXML_INSUFFICIENT_MEMORY;
            }
        }

        if( newElement->namespaceURI != 0 ) {
            pNewStackElement->namespaceUri =
                strdup( newElement->namespaceURI );
            if( pNewStackElement->namespaceUri == NULL ) {
                Parser_freeElementStackItem( pNewStackElement );
                free( pNewStackElement );
                return IXML_INSUFFICIENT_MEMORY;
            }
        }

        pCurElement = xmlParser->pCurElement;

        // insert the new element into the top of the stack
        pNewStackElement->nextElement = pCurElement;
        xmlParser->pCurElement = pNewStackElement;

    }

    return IXML_SUCCESS;
}

/*================================================================
*   Parser_popElement
*       Remove element from element stack.
*       Internal to parser only.       
*
*=================================================================*/
static void
Parser_popElement( IN Parser * xmlParser )
{
    IXML_ElementStack *pCur = NULL;
    IXML_NamespaceURI *pnsUri = NULL,
     *pNextNS = NULL;

    pCur = xmlParser->pCurElement;
    if( pCur != NULL ) {
        xmlParser->pCurElement = pCur->nextElement;

        Parser_freeElementStackItem( pCur );

        pnsUri = pCur->pNsURI;
        while( pnsUri != NULL ) {
            pNextNS = pnsUri->nextNsURI;

            Parser_freeNsURI( pnsUri );
            free( pnsUri );
            pnsUri = pNextNS;
        }

        free( pCur );
    }

}

/*================================================================
*   Parser_readFileOrBuffer
*       read a xml file or buffer contents into xml parser.
*       Internal to parser only.
*
*=================================================================*/
static int
Parser_readFileOrBuffer( IN Parser * xmlParser,
                         IN char *xmlFileName,
                         IN BOOL file )
{
    int fileSize = 0;
    int bytesRead = 0;
    FILE *xmlFilePtr = NULL;

    if( file ) {
        xmlFilePtr = fopen( xmlFileName, "rb" );
        if( xmlFilePtr == NULL ) {
            return IXML_NO_SUCH_FILE;
        } else {
            fseek( xmlFilePtr, 0, SEEK_END );
            fileSize = ftell( xmlFilePtr );
            if( fileSize == 0 ) {
                fclose( xmlFilePtr );
                return IXML_SYNTAX_ERR;
            }

            xmlParser->dataBuffer = ( char * )malloc( fileSize + 1 );
            if( xmlParser->dataBuffer == NULL ) {
                fclose( xmlFilePtr );
                return IXML_INSUFFICIENT_MEMORY;
            }

            fseek( xmlFilePtr, 0, SEEK_SET );
            bytesRead =
                fread( xmlParser->dataBuffer, 1, fileSize, xmlFilePtr );
            xmlParser->dataBuffer[bytesRead] = '\0';    // append null
            fclose( xmlFilePtr );
        }
    } else {
        xmlParser->dataBuffer = strdup( xmlFileName );
        if( xmlParser->dataBuffer == NULL ) {
            return IXML_INSUFFICIENT_MEMORY;
        }
    }

    return IXML_SUCCESS;
}

/*================================================================
*   Parser_LoadDocument
*       parses a xml file and return the DOM tree.
*       Internal to parser only
*
*=================================================================*/
int
Parser_LoadDocument( OUT IXML_Document ** retDoc,
                     IN char *xmlFileName,
                     IN BOOL file )
{
    int rc = IXML_SUCCESS;
    Parser *xmlParser = NULL;

    xmlParser = Parser_init(  );
    if( xmlParser == NULL ) {
        return IXML_INSUFFICIENT_MEMORY;
    }

    rc = Parser_readFileOrBuffer( xmlParser, xmlFileName, file );
    if( rc != IXML_SUCCESS ) {
        Parser_free( xmlParser );
        return rc;
    }

    xmlParser->curPtr = xmlParser->dataBuffer;
    rc = Parser_parseDocument( retDoc, xmlParser );
    return rc;

}

/*================================================================
*   isTopLevelElement
*       decides whether we have top level element already.
*       Internal to parser only.
*
*=================================================================*/
static int
isTopLevelElement( IN Parser * xmlParser )
{
    assert( xmlParser );
    return ( xmlParser->pCurElement == NULL );
}

/*================================================================
*   isDuplicateAttribute
*       Decide whether the new attribute is the same as an
*       existing one.
*       Internal to parser only.
*
*=================================================================*/
static int
isDuplicateAttribute( IN Parser * xmlParser,
                      IN IXML_Node * newAttrNode )
{
    IXML_Node *elementNode = NULL;
    IXML_Node *attrNode = NULL;

    elementNode = xmlParser->currentNodePtr;
    attrNode = elementNode->firstAttr;
    while( attrNode != NULL ) {
        if( strcmp( attrNode->nodeName, newAttrNode->nodeName ) == 0 ) {
            return TRUE;
        }

        attrNode = attrNode->nextSibling;
    }

    return FALSE;
}

/*================================================================
*   Parser_processAttributeName
*       processes the attribute name.
*       Internal to parser only.
*
*=================================================================*/
static int
Parser_processAttributeName( IN IXML_Document * rootDoc,
                             IN Parser * xmlParser,
                             IN IXML_Node * newNode )
{
    IXML_Attr *attr = NULL;
    int rc = IXML_SUCCESS;

    if( isDuplicateAttribute( xmlParser, newNode ) == TRUE ) {
        return IXML_SYNTAX_ERR;
    }

    rc = ixmlDocument_createAttributeEx( rootDoc, newNode->nodeName,
                                         &attr );
    if( rc != IXML_SUCCESS ) {
        return rc;
    }

    rc = ixmlNode_setNodeProperties( ( IXML_Node * ) attr, newNode );
    if( rc != IXML_SUCCESS ) {
        return rc;
    }

    rc = ixmlElement_setAttributeNode( ( IXML_Element * ) xmlParser->
                                       currentNodePtr, attr, NULL );
    return rc;
}

/*================================================================
*   Parser_processElementName
*       Processes element name 
*       Internal to parser only.
*
*=================================================================*/
static int
Parser_processElementName( IN IXML_Document * rootDoc,
                           IN Parser * xmlParser,
                           IN IXML_Node * newNode )
{
    IXML_Element *newElement = NULL;
    char *nsURI = NULL;
    int rc = IXML_SUCCESS;

    if( xmlParser->bHasTopLevel == TRUE ) {
        if( isTopLevelElement( xmlParser ) == TRUE ) {
            return IXML_SYNTAX_ERR;
        }
    } else {
        xmlParser->bHasTopLevel = TRUE;
    }

    xmlParser->savePtr = xmlParser->curPtr;
    rc = ixmlDocument_createElementEx( rootDoc, newNode->nodeName,
                                       &newElement );
    if( rc != IXML_SUCCESS ) {
        return rc;
    }

    rc = ixmlNode_setNodeProperties( ( IXML_Node * ) newElement, newNode );
    if( rc != IXML_SUCCESS ) {
        ixmlElement_free( newElement );
        return rc;
    }

    if( newNode->prefix != NULL ) { // element has namespace prefix 
        if( Parser_ElementPrefixDefined( xmlParser, newNode, &nsURI ) !=
            TRUE ) {
            // read next node to see whether it includes namespace definition
            xmlParser->pNeedPrefixNode = ( IXML_Node * ) newElement;
        } else {                // fill in the namespace
            Parser_setElementNamespace( newElement, nsURI );
        }
    } else                      // does element has default namespace
    {
        // the node may have default namespace definition
        if( Parser_hasDefaultNamespace( xmlParser, newNode, &nsURI ) ==
            TRUE ) {
            Parser_setElementNamespace( newElement, nsURI );
        } else if( xmlParser->state == eATTRIBUTE ) {
            // the default namespace maybe defined later
            xmlParser->pNeedPrefixNode = ( IXML_Node * ) newElement;
        }
    }

    rc = ixmlNode_appendChild( xmlParser->currentNodePtr,

⌨️ 快捷键说明

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