Files
Leviathan/Library/Internal/include/toolkit/c_symbol.h
T
2026-06-01 12:46:52 +02:00

250 lines
9.4 KiB
C++

#ifndef __C_SYMBOL_V2_2_H__
#define __C_SYMBOL_V2_2_H__
/*
* Simple symbol(or id) type based on string table
*
* 2005.11.25 by Young-Hyun Joo
*
* ver.2 on 2006.6.14 by Young-Hyun Joo
*/
#include <string.h>
#include <stddef.h>
#include <deque>
#include "khash.h"
struct c_symbol_dummy_lock
{
void lock() {}
void unlock() {}
};
template< typename SYMSPACE, typename LOCK = c_symbol_dummy_lock > ///< SYMSPACE : dummy type indicating symbol namespace
struct c_symbol
{
class symi;
// case sensitive version
class sym
{
public:
sym() { m_pStr = NULL; }
explicit sym( const char* pStr, bool bCopyStrOnAdd = true ) { m_pStr = c_symbol::manager().get( pStr, bCopyStrOnAdd, -1 ); }
sym( const char* pStr, size_t len ) { m_pStr = c_symbol::manager().get( pStr, true, int(len) ); }
sym( const char* pStr, int len ) { m_pStr = c_symbol::manager().get( pStr, true, len ); }
sym( const std::string & str ) { m_pStr = c_symbol::manager().get( str.c_str(), true, int(str.size()) ); }
sym( const sym& asym ) { m_pStr = asym.m_pStr; }
sym& operator = ( const sym& asym ) { m_pStr = asym.m_pStr; return *this; }
operator uintptr_t() const { return uintptr_t( m_pStr ); }
const char* c_str() const { return m_pStr; }
bool operator == ( const char* pStr ) const { return m_pStr == pStr || !strcmp( m_pStr, (pStr && !*pStr) ? NULL : pStr ); }
bool operator != ( const char* pStr ) const { return m_pStr != pStr && strcmp( m_pStr, (pStr && !*pStr) ? NULL : pStr ); }
bool operator == ( int n ) const { assert( n == NULL ); return m_pStr == (const char*)n; }
bool operator != ( int n ) const { assert( n == NULL ); return m_pStr != (const char*)n; }
bool operator == ( const sym& asym ) const { return m_pStr == asym.c_str(); }
bool operator != ( const sym& asym ) const { return m_pStr != asym.c_str(); }
bool operator == ( const symi& asym ) const { return m_pStr == asym.c_str() || !stricmp( m_pStr, asym.c_str() ); }
bool operator != ( const symi& asym ) const { return m_pStr != asym.c_str() && stricmp( m_pStr, asym.c_str() ); }
static void ClearTable() { c_symbol::manager().clear(); }
static int Count() { return c_symbol::manager().m_table.size(); }
bool TestAndSet( const char* pStr ) { m_pStr = c_symbol::manager().lookUp( pStr, -1 ); return pStr == NULL || *pStr == 0 || m_pStr; }
bool TestAndSet( const char* pStr, size_t len ) { m_pStr = c_symbol::manager().lookUp( pStr, int(len) ); return pStr == NULL || *pStr == 0 || m_pStr; }
bool TestAndSet( const char* pStr, int len ) { m_pStr = c_symbol::manager().lookUp( pStr, len ); return pStr == NULL || *pStr == 0 || m_pStr; }
private:
const char* m_pStr;
};
class csym : public sym
{
public:
csym( const char* pStr ) : sym( pStr, false ) {}
};
/// case insensitive version
class symi
{
public:
symi() { m_pStr = NULL; }
explicit symi( const char* pStr, bool bCopyStrOnAdd = true ) { m_pStr = c_symbol::manageri().get( pStr, bCopyStrOnAdd, -1 ); }
symi( const char* pStr, int len ) { m_pStr = c_symbol::manageri().get( pStr, true, len ); }
symi( const char* pStr, size_t len ) { m_pStr = c_symbol::manageri().get( pStr, true, int(len) ); }
symi( const symi& asym ) { m_pStr = asym.m_pStr; }
symi& operator = ( const symi& asym ) { m_pStr = asym.m_pStr; return *this; }
operator uintptr_t() const { return uintptr_t( m_pStr ); }
const char* c_str() const { return m_pStr; }
const char* safe_str() const { return m_pStr ? m_pStr : ""; }
bool operator == ( const char* pStr ) const { return m_pStr == pStr || !stricmp( m_pStr, (pStr && !*pStr) ? NULL : pStr ); }
bool operator != ( const char* pStr ) const { return m_pStr != pStr && stricmp( m_pStr, (pStr && !*pStr) ? NULL : pStr ); }
bool operator == ( int n ) const { assert( n == NULL ); return m_pStr == (const char*)n; }
bool operator != ( int n ) const { assert( n == NULL ); return m_pStr != (const char*)n; }
bool operator == ( const symi& asym ) const { return m_pStr == asym.c_str(); }
bool operator != ( const symi& asym ) const { return m_pStr != asym.c_str(); }
bool operator == ( const sym& asym ) const { return m_pStr == asym.c_str() || !stricmp( m_pStr, asym.c_str() ); }
bool operator != ( const sym& asym ) const { return m_pStr != asym.c_str() && stricmp( m_pStr, asym.c_str() ); }
static void ClearTable() { c_symbol::manageri().clear(); }
static int Count() { return c_symbol::manageri().m_table.size(); }
bool TestAndSet( const char* pStr ) { m_pStr = c_symbol::manageri().lookUp( pStr, -1 ); return pStr == NULL || *pStr == 0 || m_pStr; }
bool TestAndSet( const char* pStr, size_t len ) { m_pStr = c_symbol::manageri().lookUp( pStr, int(len) ); return pStr == NULL || *pStr == 0 || m_pStr; }
bool TestAndSet( const char* pStr, int len ) { m_pStr = c_symbol::manageri().lookUp( pStr, len ); return pStr == NULL || *pStr == 0 || m_pStr; }
private:
const char* m_pStr;
};
class csymi : public symi
{
public:
csymi( const char* pStr ) : symi( pStr, false ) {}
};
private:
friend class sym;
friend class symi;
template< typename HashPr >
struct symManager
{
void clear()
{
m_table.clear();
m_holder.clear();
}
const char* lookUp( const char* pStr, int len )
{
if ( pStr == NULL || *pStr == 0 )
return NULL;
m_cs.lock();
if ( len > 0 ) {
std::string key( pStr, len );
if ( !m_table.lookup( key.c_str(), pStr ) )
pStr = NULL;
} else {
if ( !m_table.lookup( pStr, pStr ) )
pStr = NULL;
}
m_cs.unlock();
return pStr;
}
const char* get( const char* pStr, bool bCopyStr, int len )
{
if ( pStr == NULL || *pStr == 0 )
return NULL;
m_cs.lock();
if ( len > 0 ) {
std::string key( pStr, len );
if ( m_table.lookup( key.c_str(), pStr ) )
{
m_cs.unlock();
return pStr;
}
m_holder.push_back( key );
pStr = m_holder.back().c_str();
} else {
if ( m_table.lookup( pStr, pStr ) )
{
m_cs.unlock();
return pStr;
}
if ( bCopyStr ) {
m_holder.push_back( std::string( pStr ) );
pStr = m_holder.back().c_str();
}
}
m_table.add( pStr, pStr );
m_cs.unlock();
return pStr;
}
KHash< const char*, HashPr > m_table;
std::deque< std::string > m_holder;
LOCK m_cs;
};
static symManager< hashPr_pchar >& manager()
{
static symManager< hashPr_pchar > mgr;
return mgr;
}
static symManager< hashPr_pchar_nocase >& manageri()
{
static symManager< hashPr_pchar_nocase > mgr;
return mgr;
}
};
template< typename SYMSPACE > inline bool operator == ( const char* pStr, const typename c_symbol< SYMSPACE >::sym& asym )
{ return pStr == asym.c_str() || !strcmp( asym.c_str(), (pStr && !*pStr) ? NULL : pStr ); }
template< typename SYMSPACE > inline bool operator != ( const char* pStr, const typename c_symbol< SYMSPACE >::sym& asym )
{ return pStr != asym.c_str() && strcmp( asym.c_str(), (pStr && !*pStr) ? NULL : pStr ); }
template< typename SYMSPACE > inline bool operator == ( const char* pStr, const typename c_symbol< SYMSPACE >::symi& asym )
{ return pStr == asym.c_str() || !stricmp( asym.c_str(), (pStr && !*pStr) ? NULL : pStr ); }
template< typename SYMSPACE > inline bool operator != ( const char* pStr, const typename c_symbol< SYMSPACE >::symi& asym )
{ return pStr != asym.c_str() && stricmp( asym.c_str(), (pStr && !*pStr) ? NULL : pStr ); }
template< typename S1, typename S2 > inline bool operator == ( const typename c_symbol<S1>::sym& asym1, const typename c_symbol<S2>::sym& asym2 )
{ return asym1.c_str() == asym2.c_str() || !strcmp( asym1.c_str(), asym2.c_str() ); }
template< typename S1, typename S2 > inline bool operator != ( const typename c_symbol<S1>::sym& asym1, const typename c_symbol<S2>::sym& asym2 )
{ return asym1.c_str() != asym2.c_str() && strcmp( asym1.c_str(), asym2.c_str() ); }
template< typename S1, typename S2 > inline bool operator == ( const typename c_symbol<S1>::sym& asym1, const typename c_symbol<S2>::symi& asym2 )
{ return asym1.c_str() == asym2.c_str() || !stricmp( asym1.c_str(), asym2.c_str() ); }
template< typename S1, typename S2 > inline bool operator != ( const typename c_symbol<S1>::sym& asym1, const typename c_symbol<S2>::symi& asym2 )
{ return asym1.c_str() != asym2.c_str() && stricmp( asym1.c_str(), asym2.c_str() ); }
template< typename S1, typename S2 > inline bool operator == ( const typename c_symbol<S1>::symi& asym1, const typename c_symbol<S2>::sym& asym2 )
{ return asym1.c_str() == asym2.c_str() || !stricmp( asym1.c_str(), asym2.c_str() ); }
template< typename S1, typename S2 > inline bool operator != ( const typename c_symbol<S1>::symi& asym1, const typename c_symbol<S2>::sym& asym2 )
{ return asym1.c_str() != asym2.c_str() && stricmp( asym1.c_str(), asym2.c_str() ); }
template< typename S1, typename S2 > inline bool operator == ( const typename c_symbol<S1>::symi& asym1, const typename c_symbol<S2>::symi& asym2 )
{ return asym1.c_str() == asym2.c_str() || !stricmp( asym1.c_str(), asym2.c_str() ); }
template< typename S1, typename S2 > inline bool operator != ( const typename c_symbol<S1>::symi& asym1, const typename c_symbol<S2>::symi& asym2 )
{ return asym1.c_str() != asym2.c_str() && stricmp( asym1.c_str(), asym2.c_str() ); }
#endif