bool CXmlManager::LoadFromFile(LPCTSTR pstrFilename, int encoding) { ASSERT(pstrFilename); Release(); HANDLE hFile = ::CreateFile(pstrFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if( hFile == INVALID_HANDLE_VALUE ) return _Failed(_T("打开文件失败")); DWORD dwSize = ::GetFileSize(hFile, NULL); if( dwSize == 0 ) return _Failed(_T("File is empty")); if ( dwSize > 4096*1024 ) return _Failed(_T("File too large")); DWORD dwRead = 0; BYTE* pByte = new BYTE[ dwSize ]; ::ReadFile( hFile, pByte, dwSize, &dwRead, NULL ); ::CloseHandle( hFile ); if( dwRead != dwSize ) { delete[] pByte; Release(); return _Failed(_T("Could not read file")); } bool ret = LoadFromMem(pByte, dwSize, encoding); delete[] pByte; return ret; }
bool CMarkup::LoadFromFile(LPCTSTR pstrFilename) { Release(); HANDLE hFile = ::CreateFile(pstrFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if( hFile == INVALID_HANDLE_VALUE ) return _Failed(_T("Error opening file")); DWORD dwSize = ::GetFileSize(hFile, NULL); if( dwSize == 0 ) return _Failed(_T("File is empty")); DWORD dwRead = 0; #ifdef _UNICODE // BUG: We don't support UNICODE file loading yet. ::CloseHandle(hFile); return false; #else m_pstrXML = static_cast<LPTSTR>(malloc(dwSize + 1)); ::ReadFile(hFile, m_pstrXML, dwSize, &dwRead, NULL); ::CloseHandle(hFile); m_pstrXML[dwSize] = '\0'; #endif // _UNICODE if( dwRead != dwSize ) { Release(); return _Failed(_T("Could not read file")); } bool bRes = _Parse(); if( !bRes ) Release(); return bRes; }
bool CMarkup::_ParseAttributes(LPTSTR& pstrText) { if( *pstrText == '>' ) return true; *pstrText++ = '\0'; _SkipWhitespace(pstrText); while( *pstrText != '\0' && *pstrText != '>' && *pstrText != '/' ) { _SkipIdentifier(pstrText); if( *pstrText != '=' ) return _Failed(_T("Error while parsing attributes"), pstrText); *pstrText++ = '\0'; TCHAR chQuote = *pstrText++; if( chQuote != '\"' && chQuote != '\'' ) return _Failed(_T("Expected attribute value"), pstrText); LPTSTR pstrDest = pstrText; if( !_ParseData(pstrText, pstrDest, chQuote) ) return false; if( *pstrText == '\0' ) return _Failed(_T("Error while parsing attribute string"), pstrText); *pstrDest = '\0'; *pstrText++ = '\0'; _SkipWhitespace(pstrText); } return true; }
bool CMarkup::LoadFromFile(const wchar_t* pstrFilename, int encoding) { Release(); CUIBuffer buf; buf = CUIFile::LoadZip(pstrFilename); if (!buf) { return _Failed(L"Could not open file"); } return LoadFromMem(buf.ptrData.get(), buf.nSize, encoding); }
bool CMarkup::_ParseAttributes(wchar_t*& pstrText) { if( *pstrText == _T('>') ) return true; *pstrText++ = _T('\0'); _SkipWhitespace(pstrText); while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('/') ) { _SkipIdentifier(pstrText); wchar_t* pstrIdentifierEnd = pstrText; _SkipWhitespace(pstrText); if( *pstrText != _T('=') ) return _Failed(L"Error while parsing attributes", pstrText); *pstrText++ = _T(' '); *pstrIdentifierEnd = _T('\0'); _SkipWhitespace(pstrText); if( *pstrText++ != _T('\"') ) return _Failed(L"Expected attribute value", pstrText); wchar_t* pstrDest = pstrText; if( !_ParseData(pstrText, pstrDest, _T('\"')) ) return false; if( *pstrText == _T('\0') ) return _Failed(L"Error while parsing attribute string", pstrText); *pstrDest = _T('\0'); if( pstrText != pstrDest ) *pstrText = _T(' '); pstrText++; _SkipWhitespace(pstrText); } return true; }
bool CXmlManager::_ParseAttributes(LPTSTR& pstrText) { if( *pstrText == _T('>') ) return true; *pstrText++ = _T('\0'); _SkipWhitespace(pstrText); while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('/') ) { _SkipIdentifier(pstrText); LPTSTR pstrIdentifierEnd = pstrText; _SkipWhitespace(pstrText); if( *pstrText != _T('=') ) return _Failed(_T("Error while parsing attributes"), pstrText); *pstrText++ = _T(' '); *pstrIdentifierEnd = _T('\0'); _SkipWhitespace(pstrText); if( *pstrText++ != _T('\"') ) return _Failed(_T("Expected attribute value"), pstrText); LPTSTR pstrDest = pstrText; if( !_ParseData(pstrText, pstrDest, _T('\"')) ) return false; if( *pstrText == _T('\0') ) return _Failed(_T("Error while parsing attribute string"), pstrText); *pstrDest = _T('\0'); *pstrText++ = _T('\0'); _SkipWhitespace(pstrText); } return true; }
bool CMarkup::_Parse(wchar_t*& pstrText, ULONG iParent) { _SkipWhitespace(pstrText); ULONG iPrevious = 0; for( ; ; ) { if( *pstrText == _T('\0') && iParent <= 1 ) return true; _SkipWhitespace(pstrText); if( *pstrText != _T('<') ) return _Failed(L"Expected start tag", pstrText); if( pstrText[1] == _T('/') ) return true; *pstrText++ = _T('\0'); _SkipWhitespace(pstrText); // Skip comment or processing directive if( *pstrText == _T('!') || *pstrText == _T('?') ) { wchar_t ch = *pstrText; if( *pstrText == _T('!') ) ch = _T('-'); while( *pstrText != _T('\0') && !(*pstrText == ch && *(pstrText + 1) == _T('>')) ) pstrText = ::CharNextW(pstrText); if( *pstrText != _T('\0') ) pstrText += 2; _SkipWhitespace(pstrText); continue; } _SkipWhitespace(pstrText); // Fill out element structure XMLELEMENT* pEl = _ReserveElement(); ULONG iPos = pEl - m_pElements; pEl->iStart = pstrText - m_pstrXML; pEl->iParent = iParent; pEl->iNext = pEl->iChild = 0; if( iPrevious != 0 ) m_pElements[iPrevious].iNext = iPos; else if( iParent > 0 ) m_pElements[iParent].iChild = iPos; iPrevious = iPos; // Parse name const wchar_t* pstrName = pstrText; _SkipIdentifier(pstrText); wchar_t* pstrNameEnd = pstrText; if( *pstrText == _T('\0') ) return _Failed(L"Error parsing element name", pstrText); // Parse attributes if( !_ParseAttributes(pstrText) ) return false; _SkipWhitespace(pstrText); if( pstrText[0] == _T('/') && pstrText[1] == _T('>') ) { pEl->iData = pstrText - m_pstrXML; *pstrText = _T('\0'); pstrText += 2; } else { if( *pstrText != _T('>') ) return _Failed(L"Expected start-tag closing", pstrText); // Parse node data pEl->iData = ++pstrText - m_pstrXML; wchar_t* pstrDest = pstrText; if( !_ParseData(pstrText, pstrDest, _T('<')) ) return false; // Determine type of next element if( *pstrText == _T('\0') && iParent <= 1 ) return true; if( *pstrText != _T('<') ) return _Failed(L"Expected end-tag start", pstrText); if( pstrText[0] == _T('<') && pstrText[1] != _T('/') ) { if( !_Parse(pstrText, iPos) ) return false; } if( pstrText[0] == _T('<') && pstrText[1] == _T('/') ) { *pstrDest = _T('\0'); *pstrText = _T('\0'); pstrText += 2; _SkipWhitespace(pstrText); SIZE_T cchName = pstrNameEnd - pstrName; if( wcsncmp(pstrText, pstrName, cchName) != 0 ) return _Failed(L"Unmatched closing tag", pstrText); pstrText += cchName; _SkipWhitespace(pstrText); if( *pstrText++ != _T('>') ) return _Failed(L"Unmatched closing tag", pstrText); } } *pstrNameEnd = _T('\0'); _SkipWhitespace(pstrText); } }
bool CMarkup::_Parse(LPTSTR& pstrText, ULONG iParent) { ULONG iPrevious = 0; for( ; ; ) { if( *pstrText == '\0' && iParent <= 1 ) return true; if( *pstrText != '<' ) return _Failed(_T("Expected start tag"), pstrText); if( pstrText[1] == '/' ) return true; *pstrText++ = '\0'; // Skip comment or processing directive if( *pstrText == '!' || *pstrText == '?' ) { TCHAR chEnd = *pstrText == '!' ? '-' : '?'; while( *pstrText != '\0' && !(*pstrText == chEnd && *(pstrText + 1) == '>') ) pstrText = ::CharNext(pstrText); if( *pstrText != '\0' ) pstrText += 2; _SkipWhitespace(pstrText); continue; } // Fill out element structure XMLELEMENT* pEl = _ReserveElement(); ULONG iPos = pEl - m_pElements; pEl->iStart = pstrText - m_pstrXML; pEl->iParent = iParent; pEl->iNext = pEl->iChild = 0; if( iPrevious != 0 ) m_pElements[iPrevious].iNext = iPos; else if( iParent > 0 ) m_pElements[iParent].iChild = iPos; iPrevious = iPos; // Parse name LPCTSTR pstrName = pstrText; _SkipIdentifier(pstrText); LPTSTR pstrNameEnd = pstrText; if( *pstrText == '\0' ) return _Failed(_T("Error parsing element name"), pstrText); // Parse attributes if( !_ParseAttributes(pstrText) ) return false; _SkipWhitespace(pstrText); if( pstrText[0] == '/' && pstrText[1] == '>' ) { pEl->iData = pstrText - m_pstrXML; *pstrText = '\0'; pstrText += 2; } else { if( *pstrText != '>' ) return _Failed(_T("Expected start-tag closing"), pstrText); // Parse node data pEl->iData = ++pstrText - m_pstrXML; LPTSTR pstrDest = pstrText; if( !_ParseData(pstrText, pstrDest, '<') ) return false; // Determine type of next element if( *pstrText == '\0' && iParent <= 1 ) return true; if( *pstrText != '<' ) return _Failed(_T("Expected end-tag start"), pstrText); if( pstrText[0] == '<' && pstrText[1] != '/' ) { if( !_Parse(pstrText, iPos) ) return false; } if( pstrText[0] == '<' && pstrText[1] == '/' ) { *pstrDest = '\0'; *pstrText = '\0'; pstrText += 2; SIZE_T cchName = pstrNameEnd - pstrName; if( _tcsncmp(pstrText, pstrName, cchName) != 0 ) return _Failed(_T("Unmatched closing tag"), pstrText); if( pstrText[cchName] != '>' ) return _Failed(_T("Unmatched closing tag"), pstrText); pstrText += cchName + 1; } } *pstrNameEnd = '\0'; _SkipWhitespace(pstrText); } }