z3-z3-4.13.0.src.util.symbol.cpp Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
symbol.cpp
Abstract:
Lisp-like symbols.
Author:
Leonardo de Moura (leonardo) 2006-09-11.
Revision History:
--*/
#include "util/symbol.h"
#include "util/mutex.h"
#include "util/str_hashtable.h"
#include "util/region.h"
#include "util/string_buffer.h"
#include
#include
#ifndef SINGLE_THREAD
#include
#endif
symbol symbol::m_dummy(TAG(void*, nullptr, 2));
const symbol symbol::null;
/**
\brief Symbol table manager. It stores the symbol strings created at runtime.
*/
namespace {
class internal_symbol_table {
region m_region; //!< Region used to store symbol strings.
str_hashtable m_table; //!< Table of created symbol strings.
DECLARE_MUTEX(lock);
public:
internal_symbol_table() {
ALLOC_MUTEX(lock);
}
~internal_symbol_table() {
DEALLOC_MUTEX(lock);
}
char const * get_str(char const * d) {
const char * result;
lock_guard _lock(*lock);
str_hashtable::entry * e;
if (m_table.insert_if_not_there_core(d, e)) {
// new entry
size_t l = strlen(d);
// store the hash-code before the string
size_t * mem = static_cast(m_region.allocate(l + 1 + sizeof(size_t)));
*mem = e->get_hash();
mem++;
result = reinterpret_cast(mem);
memcpy(mem, d, l+1);
// update the entry with the new ptr.
e->set_data(result);
}
else {
result = e->get_data();
}
SASSERT(m_table.contains(result));
return result;
}
};
}
#ifdef SINGLE_THREAD
static std::optional g_symbol_tables;
void initialize_symbols() {
if (!g_symbol_tables) {
g_symbol_tables.emplace();
}
}
void finalize_symbols() {
g_symbol_tables.reset();
}
#else
struct internal_symbol_tables {
unsigned sz;
internal_symbol_table** tables;
internal_symbol_tables(unsigned sz): sz(sz), tables(alloc_vect(sz)) {
for (unsigned i = 0; i < sz; ++i) {
tables[i] = alloc(internal_symbol_table);
}
}
~internal_symbol_tables() {
for (unsigned i = 0; i < sz; ++i) {
dealloc(tables[i]);
}
dealloc_vect(tables, sz);
}
char const * get_str(char const * d) {
auto* table = tables[string_hash(d, static_cast(strlen(d)), 251) % sz];
return table->get_str(d);
}
};
static internal_symbol_tables* g_symbol_tables = nullptr;
void initialize_symbols() {
if (!g_symbol_tables) {
unsigned num_tables = 2 * std::min((unsigned) std::thread::hardware_concurrency(), 64u);
g_symbol_tables = alloc(internal_symbol_tables, num_tables);
}
}
void finalize_symbols() {
dealloc(g_symbol_tables);
g_symbol_tables = nullptr;
}
#endif
symbol::symbol(char const * d) {
if (d == nullptr)
m_data = nullptr;
else
m_data = g_symbol_tables->get_str(d);
}
symbol & symbol::operator=(char const * d) {
m_data = d ? g_symbol_tables->get_str(d) : nullptr;
return *this;
}
std::string symbol::str() const {
SASSERT(!is_marked());
if (GET_TAG(m_data) == 0) {
return m_data ? m_data : "";
}
else {
string_buffer<128> buffer;
buffer << "k!" << UNBOXINT(m_data);
return buffer.c_str();
}
}
bool symbol::contains(char ch) const {
SASSERT(!is_marked());
if (GET_TAG(m_data) == 0) {
return strchr(m_data, ch) != nullptr;
}
else {
return false;
}
}
unsigned symbol::display_size() const {
SASSERT(!is_marked());
if (GET_TAG(m_data) == 0) {
return static_cast(strlen(m_data));
}
else {
unsigned v = UNBOXINT(m_data);
unsigned sz = 4;
v = v >> 1;
while (v > 0) {
sz++;
v = v >> 1;
}
return sz;
}
}
bool lt(symbol const & s1, symbol const & s2) {
if (s1 == s2)
return false;
if (s1.is_numerical()) {
if (!s2.is_numerical())
return true; // numeral symbols are smaller than non-numerical ones.
return s1.get_num() < s2.get_num();
}
if (s2.is_numerical()) {
SASSERT(!s1.is_numerical());
return false;
}
if (!s1.bare_str())
return true;
if (!s2.bare_str())
return false;
SASSERT(!s1.is_numerical() && !s2.is_numerical());
auto cmp = strcmp(s1.bare_str(), s2.bare_str());
SASSERT(cmp != 0);
return cmp < 0;
}