//------------------------------------------------------------------------------ // Desc: This file contains the FLAIM XML wrapper class // // Tabs: 3 // // Copyright (c) 1999-2000, 2002-2006 Novell, Inc. All Rights Reserved. // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the GNU General Public // License as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, contact Novell, Inc. // // To contact Novell about this file by physical or electronic mail, // you may find current contact information at www.novell.com // // $Id: fxml.h 3109 2006-01-19 13:07:07 -0700 (Thu, 19 Jan 2006) dsanders $ //------------------------------------------------------------------------------ #ifndef FXML_H #define FXML_H typedef struct xmlChar { FLMBYTE ucFlags; } XMLCHAR; class F_XML : public XF_RefCount, public virtual XF_Base { public: F_XML(); ~F_XML(); FLMBOOL isPubidChar( FLMUNICODE uChar); FLMBOOL isQuoteChar( FLMUNICODE uChar); FLMBOOL isWhitespace( FLMUNICODE uChar); FLMBOOL isExtender( FLMUNICODE uChar); FLMBOOL isCombiningChar( FLMUNICODE uChar); FLMBOOL isNameChar( FLMUNICODE uChar); FLMBOOL isNCNameChar( FLMUNICODE uChar); FLMBOOL isIdeographic( FLMUNICODE uChar); FLMBOOL isBaseChar( FLMUNICODE uChar); FLMBOOL isDigit( FLMUNICODE uChar); FLMBOOL isLetter( FLMUNICODE uChar); void setCharFlag( FLMUNICODE uLowChar, FLMUNICODE uHighChar, FLMUINT16 ui16Flag); FLMBOOL isNameValid( FLMUNICODE * puzName, FLMBYTE * pszName); RCODE buildCharTable( void); private: XMLCHAR * m_pCharTable; }; /*============================================================================ Desc: FLAIM's XML namespace class ============================================================================*/ class F_XMLNamespace : public XF_RefCount, public XF_Base { public: FINLINE F_XMLNamespace() { m_puzPrefix = NULL; m_puzURI = NULL; m_pNext = NULL; } FINLINE ~F_XMLNamespace() { flmAssert( !m_pNext); if( m_puzPrefix) { f_free( &m_puzPrefix); } if( m_puzURI) { f_free( &m_puzURI); } } RCODE setPrefix( FLMUNICODE * puzPrefix); RCODE setURI( FLMUNICODE * puzURI); RCODE setup( FLMUNICODE * puzPrefix, FLMUNICODE * puzURI, F_XMLNamespace * pNext); FINLINE FLMUNICODE * getPrefixPtr( void) { return( m_puzPrefix); } FINLINE FLMUNICODE * getURIPtr( void) { return( m_puzURI); } private: FLMUNICODE * m_puzPrefix; FLMUNICODE * m_puzURI; F_XMLNamespace * m_pNext; friend class F_XMLNamespaceMgr; }; /*============================================================================ Desc: Namespace manager class ============================================================================*/ class F_XMLNamespaceMgr : public XF_RefCount, public virtual XF_Base { public: F_XMLNamespaceMgr(); ~F_XMLNamespaceMgr(); RCODE findNamespace( FLMUNICODE * puzPrefix, F_XMLNamespace ** ppNamespace, FLMUINT uiMaxSearchSize = ~((FLMUINT)0)); RCODE pushNamespace( FLMUNICODE * puzPrefix, FLMUNICODE * puzNamespaceURI); RCODE pushNamespace( F_XMLNamespace * pNamespace); void popNamespaces( FLMUINT uiCount); FLMUINT getNamespaceCount( void) { return( m_uiNamespaceCount); } private: F_XMLNamespace * m_pFirstNamespace; FLMUINT m_uiNamespaceCount; }; // Typedefs typedef enum { XML_STATS } eXMLStatus; // This callback is currently only used by the non-com utilities, // which is why we haven't bothered to make it an interface typedef RCODE (* XML_STATUS_HOOK)( eXMLStatus eStatusType, void * pvArg1, void * pvArg2, void * pvArg3, void * pvUserData); /*============================================================================ Desc: FLAIM's XML import class ============================================================================*/ class F_XMLImport: public F_XML, public F_XMLNamespaceMgr { public: F_XMLImport(); ~F_XMLImport(); RCODE setup( void); void reset( void); RCODE import( F_IStream * pStream, F_Db * pDb, FLMUINT uiCollection, FLMUINT uiFlags, F_DOMNode * pNodeToLinkTo, eNodeInsertLoc eInsertLoc, F_DOMNode ** ppNewNode, XFLM_IMPORT_STATS * pImportStats); FINLINE void setStatusCallback( XML_STATUS_HOOK fnStatus, void * pvUserData) { m_fnStatus = fnStatus; m_pvCallbackData = pvUserData; } private: #define F_DEFAULT_NS_DECL 0x01 #define F_PREFIXED_NS_DECL 0x02 typedef struct xmlattr { FLMUINT uiLineNum; FLMUINT uiLineOffset; FLMUINT uiLineFilePos; FLMUINT uiLineBytes; FLMUINT uiValueLineNum; FLMUINT uiValueLineOffset; FLMUNICODE * puzPrefix; FLMUNICODE * puzLocalName; FLMUNICODE * puzVal; FLMUINT uiFlags; xmlattr * pPrev; xmlattr * pNext; } XML_ATTR; // Methods RCODE getFieldTagAndType( FLMUNICODE * puzName, FLMBOOL bOkToAdd, FLMUINT * puiTagNum, FLMUINT * puiDataType); RCODE getByte( FLMBYTE * pucByte); FINLINE void ungetByte( FLMBYTE ucByte) { // Can only unget a single byte. flmAssert( !m_ucUngetByte); m_ucUngetByte = ucByte; m_importStats.uiChars--; } RCODE getLine( void); FINLINE FLMUNICODE getChar( void) { if (m_uiCurrLineOffset == m_uiCurrLineNumChars) { return( (FLMUNICODE)0); } else { FLMUNICODE uzChar = m_puzCurrLineBuf [m_uiCurrLineOffset++]; return( uzChar); } } FINLINE FLMUNICODE peekChar( void) { if (m_uiCurrLineOffset == m_uiCurrLineNumChars) { return( (FLMUNICODE)0); } else { return( m_puzCurrLineBuf [m_uiCurrLineOffset]); } } FINLINE void ungetChar( void) { // There should never be a reason to unget past the beginning of the current // line. flmAssert( m_uiCurrLineOffset); m_uiCurrLineOffset--; } RCODE getName( FLMUINT * puiChars); RCODE getQualifiedName( FLMUINT * puiChars, FLMUNICODE ** ppuzPrefix, FLMUNICODE ** ppuzLocal, FLMBOOL * pbNamespaceDecl, FLMBOOL * pbDefaultNamespaceDecl); void getNmtoken( FLMUINT * puiChars); RCODE getPubidLiteral( void); RCODE getSystemLiteral( void); RCODE getElementValue( FLMUNICODE * puBuf, FLMUINT * puiMaxChars, FLMBOOL * pbEntity); RCODE processEntityValue( void); RCODE getEntity( FLMUNICODE * puBuf, FLMUINT * puiChars, FLMBOOL * pbTranslated, FLMUNICODE * puTransChar); RCODE processReference( FLMUNICODE * puChar = NULL); RCODE processCDATA( F_DOMNode * pParent, FLMUINT uiSavedLineNum, FLMUINT uiSavedOffset, FLMUINT uiSavedFilePos, FLMUINT uiSavedLineBytes); RCODE processAttributeList( void); RCODE processComment( F_DOMNode * pParent, FLMUINT uiSavedLineNum, FLMUINT uiSavedOffset, FLMUINT uiSavedFilePos, FLMUINT uiSavedLineBytes); RCODE processProlog( void); RCODE processXMLDecl( void); RCODE processVersion( void); RCODE processEncodingDecl( void); RCODE processSDDecl( void); RCODE processMisc( void); RCODE processDocTypeDecl( void); RCODE processPI( F_DOMNode * pParent, FLMUINT uiSavedLineNum, FLMUINT uiSavedOffset, FLMUINT uiSavedFilePos, FLMUINT uiSavedLineBytes); RCODE processElement( F_DOMNode * pNodeToLinkTo, eNodeInsertLoc eInsertLoc, F_DOMNode ** ppNewNode); RCODE unicodeToNumber64( FLMUNICODE * puzVal, FLMUINT64 * pui64Val, FLMBOOL * pbNeg); RCODE flushElementValue( F_DOMNode * pParent, FLMBYTE * pucValue, FLMUINT uiValueLen); RCODE getBinaryVal( FLMUINT * puiLength); RCODE fixNamingTag( F_DOMNode * pNode); FLMBOOL lineHasToken( const char * pszToken); RCODE processMarkupDecl( void); RCODE processPERef( void); RCODE processElementDecl( void); RCODE processEntityDecl( void); RCODE processNotationDecl( void); RCODE processAttListDecl( void); RCODE processContentSpec( void); RCODE processMixedContent( void); RCODE processChildContent( void); RCODE processAttDef( void); RCODE processAttType( void); RCODE processAttValue( XML_ATTR * pAttr); RCODE processDefaultDecl( void); RCODE processID( FLMBOOL bPublicId); RCODE processSTag( F_DOMNode * pNodeToLinkTo, eNodeInsertLoc eInsertLoc, FLMBOOL * pbHasContent, F_DOMNode ** ppElement); RCODE skipWhitespace( FLMBOOL bRequired); RCODE resizeValBuffer( FLMUINT uiSize); // Attribute management void resetAttrList( void) { m_pFirstAttr = NULL; m_pLastAttr = NULL; m_attrPool.poolReset( NULL); } RCODE allocAttribute( XML_ATTR ** ppAttr) { XML_ATTR * pAttr = NULL; RCODE rc = NE_XFLM_OK; if( RC_BAD( rc = m_attrPool.poolCalloc( sizeof( XML_ATTR), (void **)&pAttr))) { goto Exit; } if( (pAttr->pPrev = m_pLastAttr) == NULL) { m_pFirstAttr = pAttr; } else { m_pLastAttr->pNext = pAttr; } m_pLastAttr = pAttr; Exit: *ppAttr = pAttr; return( rc); } RCODE setPrefix( XML_ATTR * pAttr, FLMUNICODE * puzPrefix) { RCODE rc = NE_XFLM_OK; FLMUINT uiStrLen; if( !puzPrefix) { pAttr->puzPrefix = NULL; goto Exit; } uiStrLen = f_unilen( puzPrefix); if( RC_BAD( rc = m_attrPool.poolAlloc( sizeof( FLMUNICODE) * (uiStrLen + 1), (void **)&pAttr->puzPrefix))) { goto Exit; } f_memcpy( pAttr->puzPrefix, puzPrefix, sizeof( FLMUNICODE) * (uiStrLen + 1)); Exit: return( rc); } RCODE setLocalName( XML_ATTR * pAttr, FLMUNICODE * puzLocalName) { RCODE rc = NE_XFLM_OK; FLMUINT uiStrLen; if( !puzLocalName) { pAttr->puzLocalName = NULL; goto Exit; } uiStrLen = f_unilen( puzLocalName); if( RC_BAD( rc = m_attrPool.poolAlloc( sizeof( FLMUNICODE) * (uiStrLen + 1), (void **)&pAttr->puzLocalName))) { goto Exit; } f_memcpy( pAttr->puzLocalName, puzLocalName, sizeof( FLMUNICODE) * (uiStrLen + 1)); Exit: return( rc); } RCODE setUnicode( XML_ATTR * pAttr, FLMUNICODE * puzUnicode) { RCODE rc = NE_XFLM_OK; FLMUINT uiStrLen; if( !puzUnicode) { pAttr->puzVal = NULL; goto Exit; } uiStrLen = f_unilen( puzUnicode); if( RC_BAD( rc = m_attrPool.poolAlloc( sizeof( FLMUNICODE) * (uiStrLen + 1), (void **)&pAttr->puzVal))) { goto Exit; } f_memcpy( pAttr->puzVal, puzUnicode, sizeof( FLMUNICODE) * (uiStrLen + 1)); Exit: return( rc); } RCODE addAttributesToElement( F_DOMNode * pElement); FINLINE void setErrInfo( FLMUINT uiErrLineNum, FLMUINT uiErrLineOffset, XMLParseError eErrorType, FLMUINT uiErrLineFilePos, FLMUINT uiErrLineBytes) { m_importStats.uiErrLineNum = uiErrLineNum; m_importStats.uiErrLineOffset = uiErrLineOffset; m_importStats.eErrorType = eErrorType; m_importStats.uiErrLineFilePos = uiErrLineFilePos; m_importStats.uiErrLineBytes = uiErrLineBytes; } // Data F_Db * m_pDb; FLMUINT m_uiCollection; FLMBYTE m_ucUngetByte; FLMUNICODE * m_puzCurrLineBuf; FLMUINT m_uiCurrLineBufMaxChars; FLMUINT m_uiCurrLineNumChars; FLMUINT m_uiCurrLineOffset; FLMUINT m_uiCurrLineNum; FLMUINT m_uiCurrLineFilePos; FLMUINT m_uiCurrLineBytes; #define FLM_XML_MAX_CHARS 128 FLMUNICODE m_uChars[ FLM_XML_MAX_CHARS]; FLMBOOL m_bSetup; F_IStream * m_pStream; FLMBYTE * m_pucValBuf; FLMUINT m_uiValBufSize; // Number of Unicode characters FLMUINT m_uiFlags; FLMBOOL m_bExtendDictionary; XMLEncoding m_eXMLEncoding; XML_STATUS_HOOK m_fnStatus; void * m_pvCallbackData; XFLM_IMPORT_STATS m_importStats; F_Pool m_tmpPool; // Attribute management XML_ATTR * m_pFirstAttr; XML_ATTR * m_pLastAttr; F_Pool m_attrPool; }; #define FLM_XML_EXTEND_DICT_FLAG 0x00000001 #define FLM_XML_COMPRESS_WHITESPACE_FLAG 0x00000002 #define FLM_XML_TRANSLATE_ESC_FLAG 0x00000004 FINLINE FLMBOOL isXMLNS( FLMUNICODE * puzName) { return( (puzName [0] == FLM_UNICODE_x || puzName [0] == FLM_UNICODE_X) && (puzName [1] == FLM_UNICODE_m || puzName [1] == FLM_UNICODE_M) && (puzName [2] == FLM_UNICODE_l || puzName [2] == FLM_UNICODE_L) && (puzName [3] == FLM_UNICODE_n || puzName [3] == FLM_UNICODE_N) && (puzName [4] == FLM_UNICODE_s || puzName [4] == FLM_UNICODE_S) ? TRUE : FALSE); } #endif // FXML_H