Psst.. new poll here.
Psst.. new forums here.
Microsoft is blocking us again (TY IP Reputation!) so just use oauth login instead. :)
Paste
Pasted as C++ by dennis ( 15 years ago )
/*
BSPFile.cpp
Implementation file for the BSPFile class.
*/
#include "BSPFile.h"
BSPFile::BSPFile(const char *pszFileName)
{
m_pszFileName = pszFileName;
m_fp = fopen(m_pszFileName.c_str(), "r+");
if (!m_fp)
throw exception("Error opening file.");
DWORD nBSPVersion;
fread(&nBSPVersion;, 1, 4, m_fp);
if (nBSPVersion != BSP_VERSION)
throw exception("Bad file version.");
DWORD nEntDataSize, nEntDataOffset;
fread(&nEntDataOffset;, 1, 4, m_fp);
fread(&nEntDataSize;, 1, 4, m_fp);
if (nEntDataSize > MAX_MAP_ENTSTRING)
throw exception("Entity data too large.");
char *pszEntData = new char[nEntDataSize];
if (!pszEntData)
throw exception("Could not allocate memory for entity data.");
fseek(m_fp, nEntDataOffset, SEEK_SET);
if (fread(pszEntData, 1, nEntDataSize, m_fp) != nEntDataSize)
{
if (feof(m_fp))
throw exception("Unexpected end of file.");
else
throw exception("Read error.");
}
ParseEntityData(pszEntData, pszEntData + nEntDataSize);
delete pszEntData;
}
void BSPFile::ParseEntityData(const char *pszEntData, const char *pszEntDataEnd)
{
for (;;)
{
if (!GetToken(pszEntData, pszEntDataEnd, TRUE)) break;
if (strcmp(m_pszTok, "{"))
throw exception("Parse error: { not found.");
if (m_Ents.size() == MAX_MAP_ENTITIES)
throw exception("Parse error: maximum number of entities reached.");
m_Ents.push_back(entity_t());
entity_t *pCurrentEnt = &(m_Ents.back());
for (;;)
{
if (!GetToken(pszEntData, pszEntDataEnd, TRUE))
throw exception("Parse error: end of data reached without closing brace.");
if (!strcmp(m_pszTok, "}")) break;
if (strlen(m_pszTok) >= MAX_KEY_LENGTH)
throw exception("Parse error: token too long.");
pCurrentEnt->keys.push_back(key_t());
key_t *pCurrentKey = &(pCurrentEnt->keys.back());
pCurrentKey->pszKey = m_pszTok;
GetToken(pszEntData, pszEntDataEnd, FALSE);
if (strlen(m_pszTok) >= MAX_VALUE_LENGTH - 1)
throw exception("Parse error: token too long.");
pCurrentKey->pszValue = m_pszTok;
}
pCurrentEnt->Type = GetEntityType(m_Ents.size()-1);
}
}
BOOL BSPFile::GetToken(const char *pszEntData, const char *pszEntDataEnd, BOOL bCrossLine)
{
static char const *pCur = pszEntData;
if (pCur >= pszEntDataEnd)
{
if (!bCrossLine)
throw exception("Parse error: line is incomplete.");
else
return FALSE;
}
// skip space
while (*pCur <= 32)
{
if (pCur >= pszEntDataEnd)
{
if (!bCrossLine)
throw exception("Parse error: line is incomplete.");
else
return FALSE;
}
if (*pCur++ == 'n' && !bCrossLine)
throw exception("Parse error: line is incomplete.");
}
if (pCur >= pszEntDataEnd)
{
if (!bCrossLine)
throw exception("Parse error: line is incomplete.");
else
return FALSE;
}
char *pTok = m_pszTok;
if (*pCur == '"')
{
// quoted token
pCur++;
while (*pCur != '"')
{
*pTok++ = *pCur++;
if (pCur == pszEntDataEnd)
break;
if (pTok == &m_pszTok[MAX_TOKEN_LENGTH])
throw exception("Parse error: token too large.");
}
pCur++;
}
else
{
// regular token
while (*pCur > 32)
{
*pTok++ = *pCur++;
if (pCur == pszEntDataEnd)
break;
if (pTok == &m_pszTok[MAX_TOKEN_LENGTH])
throw exception("Parse error: token too large.");
}
}
*pTok = 0;
return TRUE;
}
BOOL BSPFile::EnumEntities(
ENUMENTITIESPROC EnumEntitiesProc, EntityType Type, const char *pszKeyFilter,
const char *pszValueFilter, const char *pszClassFilter, BOOL bExact, LONG_PTR lParam)
{
vector<entity_t>::iterator pEnt;
vector<key_t>::iterator pKey;
int nEntityID = 0;
for (pEnt = m_Ents.begin(); pEnt != m_Ents.end(); pEnt++, nEntityID++)
{
if (Type != ENT_ALL && pEnt->Type != Type)
continue;
string szClassName;
for (pKey = pEnt->keys.begin(); pKey != pEnt->keys.end(); pKey++)
{
if (pszClassFilter || pKey->pszKey == "classname")
{
if (pszClassFilter)
{
if (bExact && pKey->pszValue != pszClassFilter)
continue;
else if (pKey->pszValue.find(pszClassFilter, 0) == string::npos)
continue;
}
if (pKey->pszKey == "classname")
szClassName = pKey->pszValue;
}
if (pszKeyFilter || pszValueFilter)
{
if (bExact)
{
if (pszKeyFilter && pszValueFilter)
{
if (pKey->pszKey != pszKeyFilter ||
pKey->pszValue != pszValueFilter)
continue;
}
else if (pszKeyFilter)
{
if (pKey->pszKey != pszKeyFilter)
continue;
}
else if (pszValueFilter)
{
if (pKey->pszValue != pszValueFilter)
continue;
}
}
else
{
if (pszKeyFilter && pszValueFilter)
{
if (pKey->pszKey.find(pszKeyFilter, 0) == string::npos ||
pKey->pszValue.find(pszValueFilter, 0) == string::npos)
continue;
}
else if (pszKeyFilter)
{
if (pKey->pszKey.find(pszKeyFilter, 0) == string::npos)
continue;
}
else if (pszValueFilter)
{
if (pKey->pszValue.find(pszValueFilter, 0) == string::npos)
continue;
}
}
}
if (!EnumEntitiesProc(nEntityID, szClassName.c_str(), lParam))
return FALSE;
break;
}
}
return TRUE;
}
int BSPFile::AddEntity(const char *pszClassName)
{
if (m_Ents.size() >= MAX_MAP_ENTITIES)
return -1;
int nNewEntID = m_Ents.size() - 1;
m_Ents.push_back(entity_t());
AddKey("classname", pszClassName, nNewEntID);
return nNewEntID;
}
void BSPFile::DeleteEntity(int nEntityID)
{
}
int BSPFile::AddKey(const char *pszKey, const char *pszValue, int nEntityID)
{
m_Ents[nEntityID].keys.push_back(key_t());
key_t *pKey = &(m_Ents[nEntityID].keys.back());
pKey->pszKey = pszKey;
pKey->pszValue = pszValue;
return m_Ents[nEntityID].keys.size() - 1;
}
void BSPFile::DeleteKey(int nEntityID, int nKeyID)
{
}
BSPFile::EntityType BSPFile::GetEntityType(int nEntityID)
{
vector<key_t>::iterator pKey = m_Ents[nEntityID].keys.begin();
while (pKey != m_Ents[nEntityID].keys.end())
{
// brush ents have a "model" key with a value of "*x", where x is a non-zero number
if (pKey->pszKey == "model"
&& pKey->pszValue[0] == '*'
&& atoi(&pKey;->pszValue[1]) != 0)
{
return ENT_BRUSH;
}
pKey++;
}
// if a matching "model" value isn't found, assume it's a point ent
return ENT_POINT;
}
BSPFile::~BSPFile()
{
fclose(m_fp);
}
Revise this Paste