z3-z3-4.13.0.src.util.symbol.h Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
symbol.h
Abstract:
Lisp-like symbols.
Author:
Leonardo de Moura (leonardo) 2006-09-11.
Revision History:
--*/
#pragma once
#include
#include
#include
#include "util/util.h"
#include "util/tptr.h"
#include "util/string_buffer.h"
template
class symbol_table;
class symbol {
char const * m_data;
template
friend class symbol_table;
explicit symbol(void const * data):
m_data(reinterpret_cast(data)) {
}
bool is_marked() const {
return GET_TAG(m_data) > 1;
}
static symbol mark(symbol s) {
SASSERT(!s.is_marked());
return symbol(TAG(void *, UNTAG(void *, s.m_data), GET_TAG(s.m_data) + 2));
}
static symbol unmark(symbol s) {
SASSERT(s.is_marked());
return symbol(TAG(void *, UNTAG(void *, s.m_data), GET_TAG(s.m_data) - 2));
}
static symbol m_dummy;
public:
symbol():
m_data(nullptr) {
}
explicit symbol(char const * d);
explicit symbol(const std::string & str) : symbol(str.c_str()) {}
explicit symbol(unsigned idx):
m_data(BOXTAGINT(char const *, idx, 1)) {
#if !defined(__LP64__) && !defined(_WIN64)
SASSERT(idx < (SIZE_MAX >> PTR_ALIGNMENT));
#endif
}
static symbol dummy() { return m_dummy; }
static const symbol null;
symbol & operator=(char const * d);
friend bool operator==(symbol const & s1, symbol const & s2) { return s1.m_data == s2.m_data; }
friend bool operator!=(symbol const & s1, symbol const & s2) { return s1.m_data != s2.m_data; }
bool is_numerical() const { return GET_TAG(m_data) == 1; }
bool is_null() const { return m_data == nullptr; }
bool is_non_empty_string() const { return !is_null() && !is_numerical() && 0 != bare_str()[0]; }
unsigned int get_num() const { SASSERT(is_numerical()); return UNBOXINT(m_data); }
std::string str() const;
friend bool operator==(symbol const & s1, char const * s2) {
if (s1.m_data == nullptr && s2 == nullptr)
return true;
if (s1.m_data == nullptr || s2 == nullptr)
return false;
if (!s1.is_numerical())
return strcmp(s1.bare_str(), s2) == 0;
return s1.str() == s2;
}
friend bool operator!=(symbol const & s1, char const * s2) { return !operator==(s1, s2); }
// C-API only functions
void * c_api_symbol2ext() const { return const_cast(m_data); }
static symbol c_api_ext2symbol(void const * ptr) {
return symbol(ptr);
}
unsigned hash() const {
if (m_data == nullptr) return 0x9e3779d9;
else if (is_numerical()) return get_num();
else return static_cast(reinterpret_cast(m_data)[-1]);
}
bool contains(char c) const;
unsigned display_size() const;
char const * bare_str() const { SASSERT(!is_numerical()); return m_data; }
friend std::ostream & operator<<(std::ostream & target, symbol s) {
SASSERT(!s.is_marked());
if (GET_TAG(s.m_data) == 0) {
if (s.m_data) {
target << s.m_data;
}
else {
target << "null";
}
}
else {
target << "k!" << UNBOXINT(s.m_data);
}
return target;
}
template
friend string_buffer & operator<<(string_buffer & target, symbol s) {
SASSERT(!s.is_marked());
if (GET_TAG(s.m_data) == 0) {
if (s.m_data) {
target << s.m_data;
}
else {
target << "null";
}
}
else {
target << "k!" << UNBOXINT(s.m_data);
}
return target;
}
};
struct symbol_hash_proc {
unsigned operator()(symbol const & s) const {
return s.hash();
}
};
struct symbol_eq_proc {
bool operator()(symbol const & s1, symbol const & s2) const {
return s1 == s2;
}
};
void initialize_symbols();
void finalize_symbols();
/*
ADD_INITIALIZER('initialize_symbols();')
ADD_FINALIZER('finalize_symbols();')
*/
// total order on symbols... I did not overloaded '<' to avoid misunderstandings.
// numerical symbols are smaller than non numerical symbols.
// two numerical symbols are compared using get_num.
// two non-numerical symbols are compared using string comparison.
bool lt(symbol const & s1, symbol const & s2);