Welcome, guest! Login / Register - Why register?
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&#40;&#41;
{
 fclose(m_fp);
}

 

Revise this Paste

Your Name: Code Language: