//******************************************************************************* // COPYRIGHT NOTES // --------------- // You may use this source code, compile or redistribute it as part of your application // for free. You cannot redistribute it as a part of a software development // library without the agreement of the author. If the sources are // distributed along with the application, you should leave the original // copyright notes in the source code without any changes. // This code can be used WITHOUT ANY WARRANTIES at your own risk. // // For the latest updates to this code, check this site: // http://www.masmex.com // after Sept 2000 // // Copyright(C) 2000 Philip Oldaker //******************************************************************************* #include "stdafx.h" #include "TextParse.h" CTextParse::CTextParse() { m_szBuffer[0] = '\0'; m_pStartLine = m_szBuffer; m_pLine = m_szBuffer; m_pSavePos = m_szBuffer; } CTextParse::CTextParse(LPCTSTR pszLine) { m_szBuffer[0] = '\0'; Set(pszLine); } CTextParse::~CTextParse() { } CTextParse::CTextParse(const CTextParse &tp) { m_pLine = tp.m_pLine; m_pStartLine = tp.m_pStartLine; m_pSavePos = tp.m_pSavePos; m_szCopyBuf[0] = '\0'; m_szBuffer[0] = '\0'; _tcscpy(m_szCopyBuf,tp.m_szCopyBuf); _tcscpy(m_szBuffer,tp.m_szBuffer); } const CTextParse& CTextParse::operator=(LPCTSTR lpsz) { Set(lpsz); m_szCopyBuf[0] = '\0'; m_szBuffer[0] = '\0'; return *this; } const CTextParse& CTextParse::operator=(const CTextParse &tp) { if (*this == tp) return *this; m_pLine = tp.m_pLine; m_pStartLine = tp.m_pStartLine; m_pSavePos = tp.m_pSavePos; _tcscpy(m_szCopyBuf,tp.m_szCopyBuf); _tcscpy(m_szBuffer,tp.m_szBuffer); return *this; } BOOL CTextParse::CharExistFromCurPos(int c,BOOL bForward) { LPCTSTR p = m_pLine; if (bForward) { while (*p && *p != c) p = _tcsinc(p); } else { while (p > m_pStartLine && *p != c) p = _tcsdec(m_pLine,p); } return *p == c; } BOOL CTextParse::ValidCppCharExist(int c,BOOL bForward) { LPCTSTR p = m_pLine; while (*p && *p != c && *p != '/') p = _tcsinc(p); return *p == c; } BOOL CTextParse::CharExist(LPCTSTR str) { LPCTSTR p = m_pStartLine; while (*p && !IsToken(str,p)) p = _tcsinc(p); return *p != '\0'; } BOOL CTextParse::FindString(LPCTSTR str) { LPCTSTR p = _tcsstr(m_pLine,str); if (p) m_pLine = p; return p ? TRUE : FALSE; } BOOL CTextParse::FindChar(int c) { LPCTSTR p = _tcschr(m_pLine,c); if (p) m_pLine = p; return p ? TRUE : FALSE; } BOOL CTextParse::MoveUntilChar(int c,BOOL bForward) { if (bForward) { while(*m_pLine && *m_pLine != c) m_pLine = _tcsinc(m_pLine); return *m_pLine != '\0'; } else { while(m_pLine > m_pStartLine && *m_pLine != c) m_pLine = _tcsdec(m_pStartLine,m_pLine); return *m_pLine == c; } } BOOL CTextParse::MoveUntilChar(LPCTSTR strTok,BOOL bForward) { if (bForward) { while(*m_pLine && !IsToken(strTok,m_pLine)) m_pLine = _tcsinc(m_pLine); return *m_pLine != '\0'; } else { while(m_pLine > m_pStartLine && !IsToken(strTok,m_pLine)) m_pLine = _tcsdec(m_pStartLine,m_pLine); return IsToken(strTok,m_pLine); } } BOOL CTextParse::MoveUntilString(LPCTSTR str,BOOL bForward) { if (bForward) { while(*m_pLine && !IsString(str)) m_pLine = _tcsinc(m_pLine); return *m_pLine != '\0'; } else { while(m_pLine > m_pStartLine && !IsString(str)) m_pLine = _tcsdec(m_pStartLine,m_pLine); return IsString(str); } } BOOL CTextParse::MoveWhileChar(int c,BOOL bForward) { if (bForward) { while(*m_pLine && *m_pLine == c) m_pLine = _tcsinc(m_pLine); return *m_pLine != '\0'; } else { while(m_pLine > m_pStartLine && *m_pLine == c) m_pLine = _tcsdec(m_pStartLine,m_pLine); return *m_pLine == c; } } BOOL CTextParse::MoveWhileChar(LPCTSTR strTok,BOOL bForward) { if (bForward) { while(*m_pLine && IsToken(strTok,m_pLine)) m_pLine = _tcsinc(m_pLine); return *m_pLine != '\0'; } else { while(m_pLine > m_pStartLine && IsToken(strTok,m_pLine)) m_pLine = _tcsdec(m_pStartLine,m_pLine); return IsToken(strTok,m_pLine); } } LPCTSTR CTextParse::CopyWhileChar(int c) { for(int i=0;i < MAX_BUF && *m_pLine != '\0' && *m_pLine == c;i++) { m_szCopyBuf[i] = *m_pLine; m_pLine = _tcsinc(m_pLine); } m_szCopyBuf[i] = '\0'; return m_szCopyBuf; } LPCTSTR CTextParse::CopyUntilString(LPCTSTR pszText) { int nLen = _tcslen(pszText); for(int i=0;i < MAX_BUF && *m_pLine != '\0' && _tcsncmp(m_pLine,pszText,nLen) != 0;i++) { m_szCopyBuf[i] = *m_pLine; m_pLine = _tcsinc(m_pLine); } m_szCopyBuf[i] = '\0'; return m_szCopyBuf; } LPCTSTR CTextParse::CopyUntilChar(int c) { for(int i=0;i < MAX_BUF && *m_pLine != '\0' && *m_pLine != c;i++) { m_szCopyBuf[i] = *m_pLine; m_pLine = _tcsinc(m_pLine); } m_szCopyBuf[i] = '\0'; return m_szCopyBuf; } LPCTSTR CTextParse::CopyWhileChar(LPCTSTR strTok) { for(int i=0;i < MAX_BUF && *m_pLine != '\0' && IsToken(strTok,m_pLine);i++) { m_szCopyBuf[i] = *m_pLine; m_pLine = _tcsinc(m_pLine); } m_szCopyBuf[i] = '\0'; return m_szCopyBuf; } LPCTSTR CTextParse::CopyUntilChar(LPCTSTR strTok) { for(int i=0;i < MAX_BUF && *m_pLine != '\0' && !IsToken(strTok,m_pLine);i++) { m_szCopyBuf[i] = *m_pLine; m_pLine = _tcsinc(m_pLine); } m_szCopyBuf[i] = '\0'; return m_szCopyBuf; } LPCTSTR CTextParse::CopyFuncUntilChar(LPCTSTR strTok) { for(int i=0;i < MAX_BUF && !IsEnd() && !IsToken(strTok,m_pLine);i++) { /* if (*m_pLine == '=') { MoveUntilChar(",)"); if (m_szCopyBuf[i-1] == ' ') { i--; } }*/ if (CharAtCurrent('/')) { MoveForward(); MoveUntilChar(_T("/")); if (m_szCopyBuf[i-1] == ' ') { i--; MoveForward(); } } m_szCopyBuf[i] = *m_pLine; MoveForward(); } m_szCopyBuf[i] = '\0'; return m_szCopyBuf; } BOOL CTextParse::IsToken(LPCTSTR strTok,LPCTSTR p) { while(*strTok) { if (*p == *strTok) break; strTok = _tcsinc(strTok); } return *strTok != '\0'; } LPCTSTR CTextParse::ExtractConstructor() { MoveUntilChar('('); CopyUntilChar(')'); _tcscat(m_szCopyBuf,_T(")")); return m_szCopyBuf; } LPCTSTR CTextParse::ExtractDeclareMacro() { return CopyUntilChar('('); } LPCTSTR CTextParse::ExtractFuncName() { Reset(); // skip keywords if (_tcsncmp(m_pLine,_T("const"),5) == 0 || _tcsncmp(m_pLine,_T("afx_msg"),7) == 0 || _tcsncmp(m_pLine,_T("virtual"),7) == 0) { CopyUntilWhiteSpace(); MoveWhileWhiteSpace(); } MoveUntilChar(_T("(")); MoveUntilWhiteSpace(FALSE); if (*m_pLine == CPP_SPACE) // regular function MoveWhileWhiteSpace(); else { // else constructor or destructor // allow for virtual destructors if (_tcsncmp(m_pLine,_T("virtual"),7) == 0) { CopyUntilWhiteSpace(); MoveWhileWhiteSpace(); } Reset(); } // returning pointer or reference if (*m_pLine == '*' || *m_pLine == '&') m_pLine = _tcsinc(m_pLine); return CopyUntilChar('('); } LPCTSTR CTextParse::ExtractClassName() { MoveWhileWhiteSpace(); if (_tcsncmp(m_pLine,_T("class"),5) != 0) { m_szCopyBuf[0] = 0; return m_szCopyBuf; } Reset(); // check if derived class if (!CharExistFromCurPos(':')) { if (!CharExistFromCurPos('{')) { MoveToLastChar(); MoveWhileWhiteSpace(FALSE); MoveUntilWhiteSpace(FALSE); MoveWhileWhiteSpace(); } else { MoveUntilChar('{'); MoveUntilWhiteSpace(FALSE); MoveWhileWhiteSpace(FALSE); MoveUntilWhiteSpace(FALSE); MoveWhileWhiteSpace(); } } else { MoveUntilChar(':'); // go back and skip colon MoveUntilWhiteSpace(FALSE); MoveWhileWhiteSpace(FALSE); if (CharAtCurrent('>')) { MoveUntilChar('<',FALSE); MoveUntilWhiteSpace(FALSE); MoveWhileWhiteSpace(FALSE); } MoveUntilWhiteSpace(FALSE); MoveWhileWhiteSpace(); } return CopyUntilChar(_T(" \t<")); } LPCTSTR CTextParse::ExtractBaseClassName() { Reset(); MoveWhileWhiteSpace(); if (_tcsncmp(m_pLine,_T("class"),5) != 0) { m_szCopyBuf[0] = 0; return m_szCopyBuf; } Reset(); // check if derived class if (CharExistFromCurPos(':')) { MoveUntilChar(':'); // go back MoveWhileChar(':'); MoveWhileWhiteSpace(); MoveUntilWhiteSpace(); MoveWhileWhiteSpace(); } else { m_szCopyBuf[0] = 0; return m_szCopyBuf; } return CopyUntilChar(_T(" \t<")); } BOOL CTextParse::IsCommentBlock(LPCTSTR strStart,LPCTSTR strEnd) { LPCTSTR p = _tcsstr(m_pLine,strStart); if (p) { if (p == m_pStartLine && *(p+sizeof(TCHAR)*2) == '+') return FALSE; if (p == m_pStartLine || (p != m_pStartLine && *(p-sizeof(TCHAR)) != '/') ) { if (_tcsstr(m_pLine,strEnd) == NULL) return TRUE; } } return FALSE; } LPCTSTR CTextParse::CopyWholeWord() { bool bQuote=false; for(int i=0;i < MAX_BUF && *m_pLine != '\0';i++) { if (*m_pLine == '"') { bQuote = !bQuote; } else if (*m_pLine == ' ' && bQuote == false) { break; } m_szCopyBuf[i] = *m_pLine; m_pLine = _tcsinc(m_pLine); } SkipWhiteSpace(); m_szCopyBuf[i] = '\0'; return m_szCopyBuf; } LPCTSTR CTextParse::CopyUntilEnd() { for(int i=0;i < MAX_BUF && *m_pLine != '\0';i++) { m_szCopyBuf[i] = *m_pLine; m_pLine = _tcsinc(m_pLine); } m_szCopyBuf[i] = '\0'; return m_szCopyBuf; } bool CTextParse::FindWholeWord(LPCTSTR pszText) { bool bQuote = _tcsstr(pszText,_T("\"")) != NULL; if (*pszText == '+' || *pszText == '-') pszText = _tcsinc(pszText); int nLen = _tcslen(pszText); int nRet=-1; for(int i=0;i < MAX_BUF && *m_pLine != '\0';i++) { SkipWhiteSpace(); if (*m_pLine == '"') { if (bQuote == true) { nRet = _tcsncmp(m_pLine,pszText,nLen); if (nRet == 0) break; } MoveWhileChar('"'); MoveUntilChar('"'); MoveWhileChar('"'); } else { nRet = _tcsncmp(m_pLine,pszText,GetWordLen()); if (nRet == 0) break; SkipWord(); } } return nRet == 0; } int CTextParse::GetWordLen() { LPCTSTR p = m_pLine; for (int i=0;*p && !IsToken(CPP_WHITE_SPACE,p);i++) { p++; } return i; } bool CTextParse::SkipHTMLCommand(bool bSkipCRLF) { if (CharAtCurrent('&')) { MoveUntilChar(';'); if (CharAtCurrent(';')) MoveForward(); return true; } LPCTSTR p = m_pLine; if (bSkipCRLF) { while (*p == '\r' || *p == '\n') p = _tcsinc(p); } if (*p != '<') return false; while (*p != '>' && *p != '\0') p = _tcsinc(p); if (*p == '>') p = _tcsinc(p); m_pLine = p; return true; } void CTextParse::SkipHTMLCommands(bool bSkipCRLF) { while (SkipHTMLCommand(bSkipCRLF)) ; } BOOL CTextParse::IsValidCPP(LPCTSTR pszText) { BOOL bRet=FALSE; if (FindString(pszText)) { // check if a comment SaveCurPos(); if (!MoveUntilString(_T("//"),FALSE)) { RestorePos(); if (!MoveUntilString(_T("/*"),FALSE)) bRet = TRUE; } } Reset(); return bRet; } BOOL CTextParse::IsPrivate() { return IsValidCPP(_T("private")); } BOOL CTextParse::IsPublic() { return IsValidCPP(_T("public")); } BOOL CTextParse::IsProtected() { return IsValidCPP(_T("protected")); } BOOL CTextParse::IsVirtualFunc() { return IsValidCPP(_T("virtual")); } BOOL CTextParse::IsStartBrace() { return IsValidCPP(_T("{")); } BOOL CTextParse::IsEndBrace() { return IsValidCPP(_T("}")); } BOOL CTextParse::IsAccessSpecifier() { return IsValidCPP(_T(":")); } BOOL CTextParse::IsConstructor(LPCTSTR pszClassName) { CString sTest(pszClassName); sTest += _T("("); if (FindChar('~')) { Reset(); return FALSE; } return IsValidCPP(sTest); } BOOL CTextParse::IsMsgMap() { return FindString(_T("{{AFX_MSG")); } BOOL CTextParse::IsDeclareMacro() { BOOL bRet = FALSE; if (IsValidCPP(_T("DECLARE_"))) { if (!FindString(_T("()"))) bRet = TRUE; Reset(); } return bRet; } BOOL CTextParse::IsStartCommentBlock() { if (!FindString(_T("//"))) return FindString(_T("/*")); return FALSE; } BOOL CTextParse::IsEndCommentBlock() { return FindString(_T("*/")); } BOOL CTextParse::IsClass() { BOOL bRet=TRUE; if (FindString(_T("template"))) { bRet = FALSE; } if (!StringAtCurrent(_T("class "))) { bRet = FALSE; } Reset(); // any line comments before 'class ' MoveUntilString(_T("class ")); if (MoveUntilString(_T("//"),FALSE)) { bRet = FALSE; } Reset(); if (FindChar(_T(';'))) { bRet = FALSE; } if (FindChar(_T('#'))) { bRet = FALSE; } Reset(); return bRet; } BOOL CTextParse::ExtractArgs(CString &sRet,CStringArray &asArgs) { asArgs.RemoveAll(); SaveCurPos(); if (!CharAtCurrent('(') && FindChar('(')) { RestorePos(); SkipWhiteSpace(); if (StringAtCurrent(_T("const"))) { MoveUntilWhiteSpace(); SkipWhiteSpace(); } sRet = CopyUntilWhiteSpace(); if (MoveUntilChar('(')) { MoveForward(); } else { RestorePos(); } } while (!CharAtCurrent(')') && !IsEnd()) { SkipWhiteSpace(); if (StringAtCurrent(_T("const"))) { MoveUntilWhiteSpace(); SkipWhiteSpace(); } MoveUntilWhiteSpace(); SkipWhiteSpace(); if (StringAtCurrent(_T("void"))) break; if (CharAtCurrent('*') || CharAtCurrent('&')) MoveForward(); asArgs.Add(CopyUntilChar(_T(",)\t "))); if (CharAtCurrent(',')) MoveForward(); else SkipWhiteSpace(); } return TRUE; } LPCTSTR CTextParse::ExtractHTMLText(bool bRemoveCRLF) { return ExtractHTMLText(_T("<"),bRemoveCRLF); } LPCTSTR CTextParse::ExtractHTMLText(LPCTSTR pszUntil,bool bRemoveCRLF) { int nLen=_tcslen(pszUntil); int i=0; bool bEnd = false; while(i < MAX_BUF && *m_pLine != '\0' && _tcsncmp(m_pLine,pszUntil,nLen) != 0) { if (*m_pLine == '<' || *m_pLine == '&') { while (SkipHTMLCommand(false)) { if (_tcsncmp(m_pLine,pszUntil,nLen) == 0) { bEnd = true; break; } } } if (bEnd) break; if (bRemoveCRLF && (*m_pLine == '\n' || *m_pLine == '\r')) { m_pLine = _tcsinc(m_pLine); } else { m_szCopyBuf[i++] = *m_pLine; m_pLine = _tcsinc(m_pLine); } } m_szCopyBuf[i] = '\0'; return m_szCopyBuf; } LPCTSTR CTextParse::ExtractHTMLLink() { m_szCopyBuf[0] = '\0'; if (!FindString(_T("href="))) return m_szCopyBuf; MoveUntilChar('"'); LPCTSTR p = m_pLine; if (*p == '"') { p = _tcsinc(p); m_pLine = p; LPCTSTR pRet = CopyUntilChar('"'); MoveUntilChar('>'); MoveWhileChar('>'); return pRet; } return m_szCopyBuf; }