- Rewrote FName to use only POD types for its static data so that it can be used
without any explicit constructors being called. - Fixed: ZTwinedTorchUnlit, ZWallTorchUnlit, ZFireBullUnlit, and ZCauldronUnlit were missing game filters. SVN r79 (trunk)
This commit is contained in:
parent
d06793ad7e
commit
e78385f807
5 changed files with 265 additions and 82 deletions
220
src/name.cpp
220
src/name.cpp
|
|
@ -1,6 +1,71 @@
|
|||
/*
|
||||
** name.cpp
|
||||
** Implements int-as-string mapping.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2005-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "name.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "m_alloc.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
// The number of bytes to allocate to each NameBlock unless somebody is evil
|
||||
// and wants a really long name. In that case, it gets its own NameBlock
|
||||
// that is just large enough to hold it.
|
||||
#define BLOCK_SIZE 1024
|
||||
|
||||
// How many entries to grow the NameArray by when it needs to grow.
|
||||
#define NAME_GROW_AMOUNT 48
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
// Name text is stored in a linked list of NameBlock structures. This
|
||||
// is really the header for the block, with the remainder of the block
|
||||
// being populated by text for names.
|
||||
|
||||
struct FName::NameManager::NameBlock
|
||||
{
|
||||
size_t NextAlloc;
|
||||
NameBlock *NextBlock;
|
||||
};
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
FName::NameManager FName::NameData;
|
||||
|
||||
// Define the predefined names.
|
||||
static const char *PredefinedNames[] =
|
||||
|
|
@ -10,31 +75,38 @@ static const char *PredefinedNames[] =
|
|||
#undef xx
|
||||
};
|
||||
|
||||
int FName::Buckets[FName::HASH_SIZE];
|
||||
TArray<FName::MainName> FName::NameArray;
|
||||
bool FName::Inited;
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
FName::MainName::MainName (int next)
|
||||
: NextHash(next)
|
||||
{
|
||||
}
|
||||
//==========================================================================
|
||||
//
|
||||
// FName :: NameManager :: FindName
|
||||
//
|
||||
// Returns the index of a name. If the name does not exist and noCreate is
|
||||
// true, then it returns false. If the name does not exist and noCreate is
|
||||
// false, then the name is added to the table and its new index is returned.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FName::FindName (const char *text, bool noCreate)
|
||||
int FName::NameManager::FindName (const char *text, bool noCreate)
|
||||
{
|
||||
if (!Inited) InitBuckets ();
|
||||
if (!Inited)
|
||||
{
|
||||
InitBuckets ();
|
||||
}
|
||||
|
||||
if (text == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hash = MakeKey (text) % HASH_SIZE;
|
||||
int scanner = Buckets[hash];
|
||||
DWORD hash = MakeKey (text);
|
||||
DWORD bucket = hash % HASH_SIZE;
|
||||
int scanner = Buckets[bucket];
|
||||
|
||||
// See if the name already exists.
|
||||
while (scanner >= 0)
|
||||
{
|
||||
if (stricmp (NameArray[scanner].Text.GetChars(), text) == 0)
|
||||
if (NameArray[scanner].Hash == hash && stricmp (NameArray[scanner].Text, text) == 0)
|
||||
{
|
||||
return scanner;
|
||||
}
|
||||
|
|
@ -47,28 +119,122 @@ int FName::FindName (const char *text, bool noCreate)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Assigning the string to the name after pushing it avoids needless
|
||||
// manipulation of the string pool.
|
||||
MainName entry (Buckets[hash]);
|
||||
unsigned int index = NameArray.Push (entry);
|
||||
NameArray[index].Text = text;
|
||||
Buckets[hash] = index;
|
||||
return index;
|
||||
return AddName (text, hash, bucket);
|
||||
}
|
||||
|
||||
void FName::InitBuckets ()
|
||||
{
|
||||
size_t i;
|
||||
//==========================================================================
|
||||
//
|
||||
// FName :: NameManager :: InitBuckets
|
||||
//
|
||||
// Sets up the hash table and inserts all the default names into the table.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FName::NameManager::InitBuckets ()
|
||||
{
|
||||
Inited = true;
|
||||
for (i = 0; i < HASH_SIZE; ++i)
|
||||
{
|
||||
Buckets[i] = -1;
|
||||
}
|
||||
memset (Buckets, -1, sizeof(Buckets));
|
||||
|
||||
// Register built-in names. 'None' must be name 0.
|
||||
for (i = 0; i < countof(PredefinedNames); ++i)
|
||||
for (size_t i = 0; i < countof(PredefinedNames); ++i)
|
||||
{
|
||||
FindName (PredefinedNames[i], false);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FName :: NameManager :: AddName
|
||||
//
|
||||
// Adds a new name to the name table.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FName::NameManager::AddName (const char *text, DWORD hash, DWORD bucket)
|
||||
{
|
||||
char *textstore;
|
||||
NameBlock *block = Blocks;
|
||||
size_t len = strlen (text) + 1;
|
||||
|
||||
// Get a block large enough for the name. Only the first block in the
|
||||
// list is ever considered for name storage.
|
||||
if (block == NULL || block->NextAlloc + len >= BLOCK_SIZE)
|
||||
{
|
||||
block = AddBlock (len);
|
||||
}
|
||||
|
||||
// Copy the string into the block.
|
||||
textstore = (char *)block + block->NextAlloc;
|
||||
strcpy (textstore, text);
|
||||
block->NextAlloc += len;
|
||||
|
||||
// Add an entry for the name to the NameArray
|
||||
if (NumNames >= MaxNames)
|
||||
{
|
||||
// If no names have been defined yet, make the first allocation
|
||||
// large enough to hold all the predefined names.
|
||||
MaxNames += MaxNames == 0 ? countof(PredefinedNames) + NAME_GROW_AMOUNT : NAME_GROW_AMOUNT;
|
||||
|
||||
NameArray = (NameEntry *)M_Realloc (NameArray, MaxNames * sizeof(NameEntry));
|
||||
}
|
||||
|
||||
NameArray[NumNames].Text = textstore;
|
||||
NameArray[NumNames].Hash = hash;
|
||||
NameArray[NumNames].NextHash = Buckets[bucket];
|
||||
Buckets[bucket] = NumNames;
|
||||
|
||||
return NumNames++;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FName :: NameManager :: AddBlock
|
||||
//
|
||||
// Creates a new NameBlock at least large enough to hold the required
|
||||
// number of chars.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FName::NameManager::NameBlock *FName::NameManager::AddBlock (size_t len)
|
||||
{
|
||||
NameBlock *block;
|
||||
|
||||
len += sizeof(NameBlock);
|
||||
if (len < BLOCK_SIZE)
|
||||
{
|
||||
len = BLOCK_SIZE;
|
||||
}
|
||||
block = (NameBlock *)M_Malloc (len);
|
||||
block->NextAlloc = sizeof(NameBlock);
|
||||
block->NextBlock = Blocks;
|
||||
Blocks = block;
|
||||
return block;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FName :: NameManager :: ~NameManager
|
||||
//
|
||||
// Release all the memory used for name bookkeeping.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FName::NameManager::~NameManager()
|
||||
{
|
||||
NameBlock *block, *next;
|
||||
|
||||
for (block = Blocks; block != NULL; block = next)
|
||||
{
|
||||
next = block->NextBlock;
|
||||
free (block);
|
||||
}
|
||||
Blocks = NULL;
|
||||
|
||||
if (NameArray != NULL)
|
||||
{
|
||||
free (NameArray);
|
||||
NameArray = NULL;
|
||||
}
|
||||
NumNames = MaxNames = 0;
|
||||
memset (Buckets, -1, sizeof(Buckets));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue