📄 markupstl.cpp
字号:
strResult.append(pFound); } else { strResult += cSource; } cSource = *(++pSource); } return strResult;}string CMarkupSTL::x_TextFromDoc( int nLeft, int nRight ) const{ // // Conveniently the result is always the same or shorter in length // static char* szaCode[] = { "lt;","amp;","gt;","apos;","quot;" }; static int anCodeLen[] = { 3,4,3,5,5 }; static char* szSymbol = "<&>\'\""; string strResult; strResult.reserve( nRight - nLeft + 1 ); const char* pSource = m_strDoc.c_str(); int nChar = nLeft; char cSource = pSource[nChar]; while ( nChar <= nRight ) { if ( cSource == '&' ) { // If no match is found it means XML doc is invalid // no devastating harm done, ampersand code will just be left in result for ( int nMatch = 0; nMatch < 5; ++nMatch ) { if ( nChar <= nRight - anCodeLen[nMatch] && strncmp(szaCode[nMatch],&pSource[nChar+1],anCodeLen[nMatch]) == 0 ) { cSource = szSymbol[nMatch]; nChar += anCodeLen[nMatch]; break; } } } strResult += cSource; nChar++; cSource = pSource[nChar]; } return strResult;}void CMarkupSTL::x_DocChange( int nLeft, int nReplace, const string& strInsert ){ // Insert strInsert int m_strDoc at nLeft replacing nReplace chars // m_strDoc.replace( nLeft, nReplace, strInsert);}void CMarkupSTL::x_Adjust( int iPos, int nShift, bool bAfterPos ){ // Loop through affected elements and adjust indexes // Algorithm: // 1. update children unless bAfterPos // (if no children or bAfterPos is true, end tag of iPos not affected) // 2. update next siblings and their children // 3. go up until there is a next sibling of a parent and update end tags // 4. step 2 int iPosTop = m_aPos[iPos].iElemParent; bool bPosFirst = bAfterPos; // mark as first to skip its children while ( iPos ) { // Were we at containing parent of affected position? bool bPosTop = false; if ( iPos == iPosTop ) { // Move iPosTop up one towards root iPosTop = m_aPos[iPos].iElemParent; bPosTop = true; } // Traverse to the next update position if ( ! bPosTop && ! bPosFirst && m_aPos[iPos].iElemChild ) { // Depth first iPos = m_aPos[iPos].iElemChild; } else if ( m_aPos[iPos].iElemNext ) { iPos = m_aPos[iPos].iElemNext; } else { // Look for next sibling of a parent of iPos // When going back up, parents have already been done except iPosTop while ( (iPos=m_aPos[iPos].iElemParent) != 0 && iPos != iPosTop ) if ( m_aPos[iPos].iElemNext ) { iPos = m_aPos[iPos].iElemNext; break; } } bPosFirst = false; // Shift indexes at iPos if ( iPos != iPosTop ) m_aPos[iPos].AdjustStart( nShift ); m_aPos[iPos].AdjustEnd( nShift ); }}void CMarkupSTL::x_LocateNew( int iPosParent, int& iPosRel, int& nOffset, int nLength, int nFlags ){ // Determine where to insert new element or node // bool bInsert = (nFlags&1)?true:false; bool bHonorWhitespace = (nFlags&2)?true:false; int nStartL; if ( nLength ) { // Located at a non-element node if ( bInsert ) nStartL = nOffset; else nStartL = nOffset + nLength; } else if ( iPosRel ) { // Located at an element if ( bInsert ) // precede iPosRel nStartL = m_aPos[iPosRel].nStartL; else // follow iPosRel nStartL = m_aPos[iPosRel].nEndR + 1; } else if ( m_aPos[iPosParent].IsEmptyElement() ) { // Parent has no separate end tag, so split empty element nStartL = m_aPos[iPosParent].nStartR; } else { if ( bInsert ) // after start tag nStartL = m_aPos[iPosParent].nStartR + 1; else // before end tag nStartL = m_aPos[iPosParent].nEndL; } // Go up to start of next node, unless its splitting an empty element if ( ! bHonorWhitespace && ! m_aPos[iPosParent].IsEmptyElement() ) { TokenPos token( m_strDoc.c_str() ); token.nNext = nStartL; if ( ! x_FindToken(token) || m_strDoc[token.nL] == '<' ) nStartL = token.nL; } // Determine iPosBefore int iPosBefore = 0; if ( iPosRel ) { if ( bInsert ) { // Is iPosRel past first sibling? int iPosPrev = m_aPos[iPosParent].iElemChild; if ( iPosPrev != iPosRel ) { // Find previous sibling of iPosRel while ( m_aPos[iPosPrev].iElemNext != iPosRel ) iPosPrev = m_aPos[iPosPrev].iElemNext; iPosBefore = iPosPrev; } } else { iPosBefore = iPosRel; } } else if ( m_aPos[iPosParent].iElemChild ) { if ( ! bInsert ) { // Find last element under iPosParent int iPosLast = m_aPos[iPosParent].iElemChild; int iPosNext = iPosLast; while ( iPosNext ) { iPosLast = iPosNext; iPosNext = m_aPos[iPosNext].iElemNext; } iPosBefore = iPosLast; } } nOffset = nStartL; iPosRel = iPosBefore;}bool CMarkupSTL::x_AddElem( const char* szName, const char* szValue, bool bInsert, bool bAddChild ){ if ( bAddChild ) { // Adding a child element under main position if ( ! m_iPos ) return false; } else if ( m_iPosParent == 0 ) { // Adding root element if ( IsWellFormed() ) return false; // Locate after any version and DTD m_aPos[0].nEndL = m_strDoc.size(); } // Locate where to add element relative to current node int iPosParent, iPosBefore, nOffset = 0, nLength = 0; if ( bAddChild ) { iPosParent = m_iPos; iPosBefore = m_iPosChild; } else { iPosParent = m_iPosParent; iPosBefore = m_iPos; } int nFlags = bInsert?1:0; x_LocateNew( iPosParent, iPosBefore, nOffset, nLength, nFlags ); bool bEmptyParent = m_aPos[iPosParent].IsEmptyElement(); if ( bEmptyParent ) nOffset += 2; // include CRLF // Create element and modify positions of affected elements // If no szValue is specified, an empty element is created // i.e. either <NAME>value</NAME> or <NAME/> // int iPos = x_GetFreePos(); m_aPos[iPos].nStartL = nOffset; // Set links m_aPos[iPos].iElemParent = iPosParent; m_aPos[iPos].iElemChild = 0; m_aPos[iPos].iElemNext = 0; if ( iPosBefore ) { // Link in after iPosBefore m_aPos[iPos].iElemNext = m_aPos[iPosBefore].iElemNext; m_aPos[iPosBefore].iElemNext = iPos; } else { // First child m_aPos[iPos].iElemNext = m_aPos[iPosParent].iElemChild; m_aPos[iPosParent].iElemChild = iPos; } // Create string for insert string strInsert; int nLenName = strlen(szName); int nLenValue = szValue? strlen(szValue) : 0; if ( ! nLenValue ) { // <NAME/> empty element strInsert = "<"; strInsert += szName; strInsert += "/>\r\n\t"; m_aPos[iPos].nStartR = m_aPos[iPos].nStartL + nLenName + 2; m_aPos[iPos].nEndL = m_aPos[iPos].nStartR - 1; m_aPos[iPos].nEndR = m_aPos[iPos].nEndL + 1; } else { // <NAME>value</NAME> string strValue = x_TextToDoc( szValue ); nLenValue = strValue.size(); strInsert = "<"; strInsert += szName; strInsert += ">"; strInsert += strValue; strInsert += "</"; strInsert += szName; strInsert += ">\r\n\t"; m_aPos[iPos].nStartR = m_aPos[iPos].nStartL + nLenName + 1; m_aPos[iPos].nEndL = m_aPos[iPos].nStartR + nLenValue + 1; m_aPos[iPos].nEndR = m_aPos[iPos].nEndL + nLenName + 2; } // Insert int nReplace = 0, nLeft = m_aPos[iPos].nStartL; if ( bEmptyParent ) { string strParentTagName = x_GetTagName(iPosParent); string strFormat; strFormat = ">\r\n\t"; strFormat += strInsert; strFormat += "</"; strFormat += strParentTagName; strInsert = strFormat; nLeft -= 3; nReplace = 1; // x_Adjust is going to update all affected indexes by one amount // This will satisfy all except the empty parent // Here we pre-adjust for the empty parent // The empty tag slash is removed m_aPos[iPosParent].nStartR -= 1; // For the newly created end tag, see the following example: // <A/> (len 4) becomes <A><B/></A> (len 11) // In x_Adjust everything will be adjusted 11 - 4 = 7 // But the nEndL of element A should only be adjusted 5 m_aPos[iPosParent].nEndL -= (strParentTagName.size() + 1); } x_DocChange( nLeft, nReplace, strInsert ); x_Adjust( iPos, strInsert.size() - nReplace ); if ( bAddChild ) x_SetPos( m_iPosParent, iPosParent, iPos ); else x_SetPos( iPosParent, iPos, 0 ); return true;}bool CMarkupSTL::x_AddSubDoc( const char* szSubDoc, bool bInsert, bool bAddChild ){ // Add subdocument, parse, and modify positions of affected elements // int nOffset = 0, iPosParent, iPosBefore; if ( bAddChild ) { // Add a subdocument under main position, after current child position if ( ! m_iPos ) return false; iPosParent = m_iPos; iPosBefore = m_iPosChild; } else { iPosParent = m_iPosParent; iPosBefore = m_iPos; } int nFlags = bInsert?1:0; x_LocateNew( iPosParent, iPosBefore, nOffset, 0, nFlags ); bool bEmptyParent = m_aPos[iPosParent].IsEmptyElement(); if ( bEmptyParent ) nOffset += 2; // include CRLF // if iPosBefore is NULL, insert as first element under parent int nParentEndLBeforeAdd = m_aPos[iPosParent].nEndL; int iPosFreeBeforeAdd = m_iPosFree; // Skip version tag or DTD at start of subdocument TokenPos token( szSubDoc ); int nNodeType = x_ParseNode( token ); while ( nNodeType && nNodeType != MNT_ELEMENT ) { token.szDoc = &szSubDoc[token.nNext]; token.nNext = 0; nNodeType = x_ParseNode( token ); } string strInsert = token.szDoc; // Insert subdocument m_aPos[iPosParent].nEndL = nOffset; int nReplace = 0, nLeft = nOffset; string strParentTagName; if ( bEmptyParent ) { strParentTagName = x_GetTagName(iPosParent); string strFormat; strFormat = ">\r\n\t"; strFormat += strInsert; strFormat += "</"; strFormat += strParentTagName; strInsert = strFormat; m_aPos[iPosParent].nEndL = m_aPos[iPosParent].nStartR + 2; nLeft = m_aPos[iPosParent].nStartR - 1; nReplace = 1; } x_DocChange( nLeft, nReplace, strInsert ); // Parse subdocument int iPos = x_ParseElem(iPosParent); m_aPos[iPosParent].nEndL = nParentEndLBeforeAdd; if ( iPos <= 0 ) { // Abort because not well-formed string strRevert = bEmptyParent?"/":""; x_DocChange( nLeft, strInsert.size(), strRevert ); m_iPosFree = iPosFreeBeforeAdd; return false; } else { // Link in parent and siblings m_aPos[iPos].iElemParent = iPosParent; if ( iPosBefore ) { m_aPos[iPos].iElemNext = m_aPos[iPosBefore].iElemNext; m_aPos[iPosBefore].iElemNext = iPos; } else { m_aPos[iPos].iElemNext = m_aPos[iPosParent].iElemChild; m_aPos[iPosParent].iElemChild = iPos; } // Make empty parent pre-adjustment if ( bEmptyParent ) { m_aPos[iPosParent].nStartR -= 1; m_aPos[iPosParent].nEndL -= (strParentTagName.size() + 1); } // Adjust, but don't adjust children of iPos (bAfterPos=true) x_Adjust( iPos, strInsert.size() - nReplace, true ); } // Set position to top element of subdocument if ( bAddChild ) x_SetPos( m_iPosParent, iPosParent, iPos ); else // Main x_SetPos( m_iPosParent, iPos, 0 ); return true;}int CMarkupSTL::x_RemoveElem( int iPos ){ // Remove element and all contained elements // Return new position // int iPosParent = m_aPos[iPos].iElemParent; // Find previous sibling and bypass removed element // This leaves orphan positions in m_aPos array int iPosLook = m_aPos[iPosParent].iElemChild; int iPosPrev = 0; while ( iPosLook != iPos ) { iPosPrev = iPosLook; iPosLook = m_aPos[iPosLook].iElemNext; } if ( iPosPrev ) m_aPos[iPosPrev].iElemNext = m_aPos[iPos].iElemNext; else m_aPos[iPosParent].iElemChild = m_aPos[iPos].iElemNext; // Remove from document // Links have been changed to go around removed element // But element position and links are still valid int nAfterEnd = m_aPos[iPos].nEndR + 1; TokenPos token( m_strDoc.c_str() ); token.nNext = nAfterEnd; if ( ! x_FindToken(token) || token.szDoc[token.nL] == '<' ) nAfterEnd = token.nL; int nLen = nAfterEnd - m_aPos[iPos].nStartL; x_DocChange( m_aPos[iPos].nStartL, nLen, string() ); x_Adjust( iPos, - nLen, true ); return iPosPrev;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -