This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

258 lines
7.9 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines a symbol table
//
// $Header: $
// $NoKeywords: $
//===========================================================================//
#ifndef UTLSYMBOL_H
#define UTLSYMBOL_H
#ifdef _WIN32
#pragma once
#endif
#include "../tier0/threadtools.h"
#include "utlrbtree.h"
#include "utlvector.h"
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
class CUtlSymbolTable;
class CUtlSymbolTableMT;
//-----------------------------------------------------------------------------
// This is a symbol, which is a easier way of dealing with strings.
//-----------------------------------------------------------------------------
typedef unsigned short UtlSymId_t;
#define UTL_INVAL_SYMBOL ((UtlSymId_t)~0)
class CUtlSymbol {
public:
// constructor, destructor
CUtlSymbol() : m_Id(UTL_INVAL_SYMBOL) {}
CUtlSymbol(UtlSymId_t id) : m_Id(id) {}
CUtlSymbol(const char* pStr);
CUtlSymbol(CUtlSymbol const& sym) : m_Id(sym.m_Id) {}
// operator=
CUtlSymbol& operator=(CUtlSymbol const& src) {
m_Id = src.m_Id;
return *this;
}
// operator==
bool operator==(CUtlSymbol const& src) const { return m_Id == src.m_Id; }
bool operator==(const char* pStr) const;
// Is valid?
bool IsValid() const { return m_Id != UTL_INVAL_SYMBOL; }
// Gets at the symbol
operator UtlSymId_t const() const { return m_Id; }
// Gets the string associated with the symbol
const char* String() const;
// Modules can choose to disable the static symbol table so to prevent
// accidental use of them.
static void DisableStaticSymbolTable();
protected:
UtlSymId_t m_Id;
// Initializes the symbol table
static void Initialize();
// returns the current symbol table
static CUtlSymbolTableMT* CurrTable();
// The standard global symbol table
static CUtlSymbolTableMT* s_pSymbolTable;
static bool s_bAllowStaticSymbolTable;
friend class CCleanupUtlSymbolTable;
};
//-----------------------------------------------------------------------------
// CUtlSymbolTable:
// description:
// This class defines a symbol table, which allows us to perform mappings
// of strings to symbols and back. The symbol class itself contains
// a static version of this class for creating global strings, but this
// class can also be instanced to create local symbol tables.
//-----------------------------------------------------------------------------
class CUtlSymbolTable {
public:
// constructor, destructor
CUtlSymbolTable(int growSize = 0, int initSize = 32,
bool caseInsensitive = false);
~CUtlSymbolTable();
// Finds and/or creates a symbol based on the string
CUtlSymbol AddString(const char* pString);
// Finds the symbol for pString
CUtlSymbol Find(const char* pString) const;
// Look up the string associated with a particular symbol
const char* String(CUtlSymbol id) const;
// Remove all symbols in the table.
void RemoveAll();
int GetNumStrings(void) const { return m_Lookup.Count(); }
protected:
class CStringPoolIndex {
public:
inline CStringPoolIndex() {}
inline CStringPoolIndex(unsigned short iPool, unsigned short iOffset) {
m_iPool = iPool;
m_iOffset = iOffset;
}
inline bool operator==(const CStringPoolIndex& other) const {
return m_iPool == other.m_iPool && m_iOffset == other.m_iOffset;
}
unsigned short m_iPool; // Index into m_StringPools.
unsigned short m_iOffset; // Index into the string pool.
};
class CLess {
public:
CLess(int ignored = 0) {
} // permits default initialization to NULL in CUtlRBTree
bool operator!() const { return false; }
bool operator()(const CStringPoolIndex& left,
const CStringPoolIndex& right) const;
};
// Stores the symbol lookup
class CTree : public CUtlRBTree<CStringPoolIndex, unsigned short, CLess> {
public:
CTree(int growSize, int initSize)
: CUtlRBTree<CStringPoolIndex, unsigned short, CLess>(growSize,
initSize) {}
friend class CUtlSymbolTable::CLess; // Needed to allow CLess to
// calculate pointer to symbol
// table
};
struct StringPool_t {
int m_TotalLen; // How large is
int m_SpaceUsed;
char m_Data[1];
};
CTree m_Lookup;
bool m_bInsensitive;
mutable const char* m_pUserSearchString;
// stores the string data
CUtlVector<StringPool_t*> m_StringPools;
private:
int FindPoolWithSpace(int len) const;
const char* StringFromIndex(const CStringPoolIndex& index) const;
friend class CLess;
};
class CUtlSymbolTableMT : private CUtlSymbolTable {
public:
CUtlSymbolTableMT(int growSize = 0, int initSize = 32,
bool caseInsensitive = false)
: CUtlSymbolTable(growSize, initSize, caseInsensitive) {}
CUtlSymbol AddString(const char* pString) {
m_lock.LockForWrite();
CUtlSymbol result = CUtlSymbolTable::AddString(pString);
m_lock.UnlockWrite();
return result;
}
CUtlSymbol Find(const char* pString) const {
m_lock.LockForRead();
CUtlSymbol result = CUtlSymbolTable::Find(pString);
m_lock.UnlockRead();
return result;
}
const char* String(CUtlSymbol id) const {
m_lock.LockForRead();
const char* pszResult = CUtlSymbolTable::String(id);
m_lock.UnlockRead();
return pszResult;
}
private:
#if defined(WIN32) || defined(_WIN32)
mutable CThreadSpinRWLock m_lock;
#else
mutable CThreadRWLock m_lock;
#endif
};
//-----------------------------------------------------------------------------
// CUtlFilenameSymbolTable:
// description:
// This class defines a symbol table of individual filenames, stored more
// efficiently than a standard symbol table. Internally filenames are
//broken up into file and path entries, and a file handle class allows
//convenient access to these.
//-----------------------------------------------------------------------------
// The handle is a CUtlSymbol for the dirname and the same for the filename, the
// accessor
// copies them into a static char buffer for return.
typedef void* FileNameHandle_t;
#define FILENAMEHANDLE_INVALID 0
// Symbol table for more efficiently storing filenames by breaking paths and
// filenames apart. Refactored from BaseFileSystem.h
class CUtlFilenameSymbolTable {
// Internal representation of a FileHandle_t
// If we get more than 64K filenames, we'll have to revisit...
// Right now CUtlSymbol is a short, so this packs into an int/void * pointer
// size...
struct FileNameHandleInternal_t {
FileNameHandleInternal_t() {
path = 0;
file = 0;
}
// Part before the final '/' character
unsigned short path;
// Part after the final '/', including extension
unsigned short file;
};
class HashTable;
public:
CUtlFilenameSymbolTable();
~CUtlFilenameSymbolTable();
FileNameHandle_t FindOrAddFileName(const char* pFileName);
FileNameHandle_t FindFileName(const char* pFileName);
int PathIndex(const FileNameHandle_t& handle) {
return ((const FileNameHandleInternal_t*)&handle)->path;
}
bool String(const FileNameHandle_t& handle, char* buf, int buflen);
void RemoveAll();
private:
// CCountedStringPool m_StringPool;
HashTable* m_Strings;
mutable CThreadSpinRWLock m_lock;
};
#endif // UTLSYMBOL_H