/***************************************************************************/
/* NOTE: */
/* This document is copyright (c) by Oz Solomonovich, and is bound by the */
/* MIT open source license (www.opensource.org/licenses/mit-license.html). */
/* See License.txt for more information. */
/***************************************************************************/
#include "StdAfx.h"
#include "Resource.h"
#include "Config.h"
#include "ParserManager.h"
#include "CPP_Parser.h"
#include "VB_Parser.h"
#include "SimpleParsers.h"
static const CString s_CfgIDString = "V2";
static IFileParser *s_arrParsers[] =
{
new CCParser(),
new CVBParser(),
new CINIParser(),
new CMakeFileParser(),
new CPlainTextParser()
};
CParserManager::CParserManager()
{
}
CParserManager::~CParserManager()
{
for (int i = 0; i < countof(s_arrParsers); ++i)
{
delete s_arrParsers[i];
}
}
CParserManager& CParserManager::Get()
{
static CParserManager instance;
return instance;
}
void CParserManager::LoadConfig()
{
SetState(cfg_sExtList);
}
void CParserManager::SaveConfig()
{
GetState(cfg_sExtList);
}
void CParserManager::GetState(state_t& state) const
{
state = s_CfgIDString;
POSITION p = m_mapExtToParser.GetStartPosition();
parser_fileext_pair pair;
while (p)
{
if (!state.IsEmpty()) state += ";";
m_mapExtToParser.GetNextAssoc(p, pair.sExt, pair.pParser);
state += pair.sExt;
state += '/';
state += pair.pParser->GetParserCfgCode();
}
}
void CParserManager::SetState(state_t& state)
{
m_mapExtToParser.RemoveAll();
// validate the the configuration string has a proper ID
if (state.GetLength() < s_CfgIDString.GetLength() ||
state.Left(s_CfgIDString.GetLength()) != s_CfgIDString)
{
ResetPairs();
}
else
{
// highly inefficient, but simple code
int i = 1;
CString strPair, strExt, strParser;
while (AfxExtractSubString(strPair, state, i++, ';'))
{
if (!AfxExtractSubString(strExt, strPair, 0, '/') ||
!AfxExtractSubString(strParser, strPair, 1, '/'))
{
continue;
}
// find parser with this sig
for (int iParser = 0; iParser < countof(s_arrParsers); ++iParser)
{
if (strParser == s_arrParsers[iParser]->GetParserCfgCode())
{
strExt.MakeLower();
m_mapExtToParser[strExt] = s_arrParsers[iParser];
break;
}
}
}
}
}
void CParserManager::GetParsers(OUT IFileParser **& pParserArray,
OUT int& iCount) const
{
pParserArray = s_arrParsers;
iCount = countof(s_arrParsers);
}
IFileParser *CParserManager::GetParserForFile(const char *pszFileName) const
{
CString cStrFileName(pszFileName);
CString cStrExt;
int iPos = cStrFileName.ReverseFind('.') - 1;
if ( iPos >= 0 )
cStrExt = cStrFileName.Mid(iPos + 2);
cStrExt.MakeLower();
IFileParser *pParser;
if (m_mapExtToParser.Lookup(cStrExt, pParser))
{
return pParser;
}
return NULL;
}
void CParserManager::GetPairs(OUT PairArray& arr) const
{
arr.RemoveAll();
POSITION p = m_mapExtToParser.GetStartPosition();
parser_fileext_pair pair;
while (p)
{
m_mapExtToParser.GetNextAssoc(p, pair.sExt, pair.pParser);
arr.Add(pair);
}
}
void CParserManager::AddPair(const parser_fileext_pair& pair)
{
ASSERT(pair.pParser != NULL);
CString sExtLower = pair.sExt;
sExtLower.MakeLower();
ASSERT(!m_mapExtToParser.RemoveKey(sExtLower));
m_mapExtToParser[sExtLower] = pair.pParser;
}
void CParserManager::RemovePair(LPCTSTR pszPair)
{
CString sExt(pszPair);
sExt.MakeLower();
VERIFY(m_mapExtToParser.RemoveKey(sExt));
}
void CParserManager::ResetPairs()
{
m_mapExtToParser.RemoveAll();
CString sExt;
for (int iParser = 0; iParser < countof(s_arrParsers); ++iParser)
{
LPCTSTR pszExts = s_arrParsers[iParser]->GetDefaultExtensions();
int i = 0;
while (AfxExtractSubString(sExt, pszExts, i++, '/'))
{
sExt.MakeLower();
m_mapExtToParser[sExt] = s_arrParsers[iParser];
}
}
}