- 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:
Randy Heit 2006-05-05 04:37:10 +00:00
parent d06793ad7e
commit e78385f807
5 changed files with 264 additions and 81 deletions

View file

@ -464,7 +464,7 @@ DObject::DObject ()
: ObjectFlags(0), Class(0) : ObjectFlags(0), Class(0)
{ {
if (FreeIndices.Pop (Index)) if (FreeIndices.Pop (Index))
Objects[Index] = this; Objects[(unsigned int)Index] = this;
else else
Index = Objects.Push (this); Index = Objects.Push (this);
} }
@ -473,7 +473,7 @@ DObject::DObject (TypeInfo *inClass)
: ObjectFlags(0), Class(inClass) : ObjectFlags(0), Class(inClass)
{ {
if (FreeIndices.Pop (Index)) if (FreeIndices.Pop (Index))
Objects[Index] = this; Objects[(unsigned int)Index] = this;
else else
Index = Objects.Push (this); Index = Objects.Push (this);
} }
@ -559,7 +559,7 @@ void DObject::RemoveFromArray ()
} }
else if (Objects.Size() > Index) else if (Objects.Size() > Index)
{ {
Objects[Index] = NULL; Objects[(unsigned int)Index] = NULL;
FreeIndices.Push (Index); FreeIndices.Push (Index);
} }
} }

View file

@ -551,7 +551,7 @@ FPNGChunkFile::FPNGChunkFile (FILE *file, DWORD id, size_t chunklen)
: FCompressedFile (file, EReading, true, false), m_ChunkID (id) : FCompressedFile (file, EReading, true, false), m_ChunkID (id)
{ {
m_Buffer = (byte *)M_Malloc (chunklen); m_Buffer = (byte *)M_Malloc (chunklen);
m_BufferSize = chunklen; m_BufferSize = (unsigned int)chunklen;
fread (m_Buffer, chunklen, 1, m_File); fread (m_Buffer, chunklen, 1, m_File);
// Skip the CRC for now. Maybe later it will be used. // Skip the CRC for now. Maybe later it will be used.
fseek (m_File, 4, SEEK_CUR); fseek (m_File, 4, SEEK_CUR);

View file

@ -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 <string.h>
#include "name.h" #include "name.h"
#include "c_dispatch.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. // Define the predefined names.
static const char *PredefinedNames[] = static const char *PredefinedNames[] =
@ -10,31 +75,38 @@ static const char *PredefinedNames[] =
#undef xx #undef xx
}; };
int FName::Buckets[FName::HASH_SIZE]; // CODE --------------------------------------------------------------------
TArray<FName::MainName> FName::NameArray;
bool FName::Inited;
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::NameManager::FindName (const char *text, bool noCreate)
{ {
if (!Inited)
{
InitBuckets ();
} }
int FName::FindName (const char *text, bool noCreate)
{
if (!Inited) InitBuckets ();
if (text == NULL) if (text == NULL)
{ {
return 0; return 0;
} }
int hash = MakeKey (text) % HASH_SIZE; DWORD hash = MakeKey (text);
int scanner = Buckets[hash]; DWORD bucket = hash % HASH_SIZE;
int scanner = Buckets[bucket];
// See if the name already exists. // See if the name already exists.
while (scanner >= 0) while (scanner >= 0)
{ {
if (stricmp (NameArray[scanner].Text.GetChars(), text) == 0) if (NameArray[scanner].Hash == hash && stricmp (NameArray[scanner].Text, text) == 0)
{ {
return scanner; return scanner;
} }
@ -47,28 +119,122 @@ int FName::FindName (const char *text, bool noCreate)
return 0; return 0;
} }
// Assigning the string to the name after pushing it avoids needless return AddName (text, hash, bucket);
// manipulation of the string pool.
MainName entry (Buckets[hash]);
unsigned int index = NameArray.Push (entry);
NameArray[index].Text = text;
Buckets[hash] = index;
return index;
} }
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; Inited = true;
for (i = 0; i < HASH_SIZE; ++i) memset (Buckets, -1, sizeof(Buckets));
{
Buckets[i] = -1;
}
// Register built-in names. 'None' must be name 0. // 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); 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));
}

View file

@ -1,8 +1,40 @@
/*
** name.h
**
**---------------------------------------------------------------------------
** 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.
**---------------------------------------------------------------------------
**
*/
#ifndef NAME_H #ifndef NAME_H
#define NAME_H #define NAME_H
#include "zstring.h" #include "doomtype.h"
#include "tarray.h"
enum ENamedName enum ENamedName
{ {
@ -15,28 +47,24 @@ class FName
{ {
public: public:
FName () : Index(0) {} FName () : Index(0) {}
FName (const char *text) { Index = FindName (text, false); } FName (const char *text) { Index = NameData.FindName (text, false); }
FName (const FString &text) { Index = FindName (text.GetChars(), false); } FName (const char *text, bool noCreate) { Index = NameData.FindName (text, noCreate); }
FName (const char *text, bool noCreate) { Index = FindName (text, noCreate); }
FName (const FString &text, bool noCreate) { Index = FindName (text.GetChars(), noCreate); }
FName (const FName &other) { Index = other.Index; } FName (const FName &other) { Index = other.Index; }
FName (ENamedName index) { Index = index; } FName (ENamedName index) { Index = index; }
// ~FName () {} // Names can be added but never removed. // ~FName () {} // Names can be added but never removed.
int GetIndex() const { return Index; } int GetIndex() const { return Index; }
operator int() const { return Index; } operator int() const { return Index; }
const FString &GetText() const { return NameArray[Index].Text; } const char *GetChars() const { return NameData.NameArray[Index].Text; }
const char *GetChars() const { return NameArray[Index].Text.GetChars(); } operator const char *() const { return NameData.NameArray[Index].Text; }
FName &operator = (const char *text) { Index = FindName (text, false); return *this; } FName &operator = (const char *text) { Index = NameData.FindName (text, false); return *this; }
FName &operator = (const FString &text) { Index = FindName (text.GetChars(), false); return *this; }
FName &operator = (const FName &other) { Index = other.Index; return *this; } FName &operator = (const FName &other) { Index = other.Index; return *this; }
FName &operator = (ENamedName index) { Index = index; return *this; } FName &operator = (ENamedName index) { Index = index; return *this; }
int SetName (const char *text, bool noCreate) { return Index = FindName (text, false); } int SetName (const char *text, bool noCreate=false) { return Index = NameData.FindName (text, noCreate); }
int SetName (const FString &text, bool noCreate) { return Index = FindName (text.GetChars(), false); }
bool IsValidName() const { return (unsigned int)Index < NameArray.Size(); } bool IsValidName() const { return (unsigned)Index < (unsigned)NameData.NumNames; }
// Note that the comparison operators compare the names' indices, not // Note that the comparison operators compare the names' indices, not
// their text, so they cannot be used to do a lexicographical sort. // their text, so they cannot be used to do a lexicographical sort.
@ -57,47 +85,36 @@ public:
private: private:
int Index; int Index;
enum { HASH_SIZE = 256 }; struct NameEntry
struct MainName
{ {
MainName (int next); char *Text;
MainName (const MainName &other) : Text(other.Text), NextHash(other.NextHash) {} DWORD Hash;
MainName () {}
FString Text;
int NextHash; int NextHash;
void *operator new (size_t size, MainName *addr)
{
return addr;
}
void operator delete (void *, MainName *)
{
}
};
static TArray<MainName> NameArray;
static int Buckets[HASH_SIZE];
static int FindName (const char *text, bool noCreate);
static void InitBuckets ();
static bool Inited;
#ifndef __GNUC__
template<> friend void CopyForTArray<MainName> (MainName &dst, MainName &src)
{
dst.NextHash = src.NextHash;
CopyForTArray (dst.Text, src.Text);
}
#else
template<class MainName> friend inline void CopyForTArray (MainName &dst, MainName &src);
#endif
}; };
#ifdef __GNUC__ struct NameManager
template<> inline void CopyForTArray<FName::MainName> (FName::MainName &dst, FName::MainName &src)
{ {
dst.NextHash = src.NextHash; // No constructor because we can't ensure that it actually gets
CopyForTArray (dst.Text, src.Text); // called before any FNames are constructed during startup. This
} // means this struct must only exist in the program's BSS section.
#endif ~NameManager();
enum { HASH_SIZE = 256 };
struct NameBlock;
NameBlock *Blocks;
NameEntry *NameArray;
int NumNames, MaxNames;
int Buckets[HASH_SIZE];
int FindName (const char *text, bool noCreate);
int AddName (const char *text, DWORD hash, DWORD bucket);
NameBlock *AddBlock (size_t len);
void InitBuckets ();
bool Inited;
};
static NameManager NameData;
};
#endif #endif

View file

@ -1082,7 +1082,7 @@ void FFontChar2::MakeTexture ()
I_FatalError ("The font %s is corrupt", name); I_FatalError ("The font %s is corrupt", name);
} }
if (Spans!=NULL) Spans = CreateSpans (Pixels); Spans = CreateSpans (Pixels);
} }
//=========================================================================== //===========================================================================