Symbol: switch to using the symbol-table as backing implementation (#158)
...which means, from now on identical input strings will produce the same Symbol object (embedded pointer). TODO: does not handle null pointers passed in as c-String properly
This commit is contained in:
parent
f9c3b8b61c
commit
29b8b2b8bc
5 changed files with 116 additions and 63 deletions
|
|
@ -48,6 +48,7 @@ extern "C" {
|
|||
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
using std::forward;
|
||||
using boost::hash_combine;
|
||||
|
||||
|
||||
|
|
@ -92,17 +93,16 @@ namespace lib {
|
|||
namespace { // quick-n-dirty symbol table implementation
|
||||
|
||||
/** @warning grows eternally, never shrinks */
|
||||
std::unordered_set<string> symbolTable; ////////////////////////////////TICKET #158 replace by symbol table
|
||||
std::unordered_set<string> symbolTable; ////////////////////////////////TICKET #158 replace by symbol table class
|
||||
}
|
||||
|
||||
/** @internal quick-n-dirty hack, used as workaround for creating command-IDs on the fly */
|
||||
Symbol
|
||||
internedString (string&& symbolString)
|
||||
{
|
||||
auto res = symbolTable.insert (std::forward<string> (symbolString));
|
||||
return Symbol (res.first->c_str());
|
||||
}
|
||||
/////////////////////////////////////(End)symbol-table hack
|
||||
/** create Symbol by symbol table lookup.
|
||||
* @note identical strings will be mapped to
|
||||
* the same Literal (embedded pointer)
|
||||
*/
|
||||
Symbol::Symbol (string&& definition)
|
||||
: Literal{symbolTable.insert(forward<string> (definition)).first->c_str()}
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -88,45 +88,36 @@ namespace lib {
|
|||
|
||||
|
||||
/** Token or Atom with distinct identity
|
||||
* @todo define a real Symbol class, i.e. same literal string==same pointer,
|
||||
* @note same literal string==same pointer representation
|
||||
*/
|
||||
class Symbol
|
||||
: public Literal
|
||||
{
|
||||
public:
|
||||
Symbol (const char* lit =0)
|
||||
: Literal(lit)
|
||||
explicit
|
||||
Symbol (std::string&& definition);
|
||||
|
||||
Symbol()
|
||||
: Symbol{""}
|
||||
{ }
|
||||
|
||||
Symbol (Symbol const& o)
|
||||
: Literal(o)
|
||||
|
||||
Symbol (const char* lit)
|
||||
: Symbol{std::string(lit)}
|
||||
{ }
|
||||
|
||||
Symbol (Literal const& base, std::string ext)
|
||||
: Literal(NULL)
|
||||
{
|
||||
UNIMPLEMENTED ("symbol table");
|
||||
}
|
||||
: Symbol{std::string(base)+"."+ext}
|
||||
{ }
|
||||
|
||||
Symbol (Literal const& base, Literal ext)
|
||||
: Literal(NULL)
|
||||
{
|
||||
UNIMPLEMENTED ("symbol table");
|
||||
}
|
||||
Symbol (Literal const& base, const char* ext)
|
||||
: Symbol{base, std::string(ext)}
|
||||
{ }
|
||||
|
||||
explicit
|
||||
Symbol (std::string definition)
|
||||
: Literal(NULL)
|
||||
{
|
||||
UNIMPLEMENTED ("symbol table");
|
||||
}
|
||||
Symbol (Symbol const&) = default;
|
||||
Symbol (Symbol &&) = default;
|
||||
|
||||
Symbol&
|
||||
operator= (Literal const& otherSym)
|
||||
{
|
||||
Literal::operator= (otherSym);
|
||||
return *this;
|
||||
}
|
||||
Symbol& operator= (Symbol const&) = default;
|
||||
Symbol& operator= (Symbol &&) = default;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -145,32 +136,98 @@ namespace lib {
|
|||
inline bool
|
||||
operator!= (Literal sy1, Literal sy2)
|
||||
{
|
||||
return ! (sy1 == sy2);
|
||||
return not (sy1 == sy2);
|
||||
}
|
||||
|
||||
/** @note two symbols are equal iff
|
||||
* they use the same symbol table entry
|
||||
*/
|
||||
inline bool
|
||||
operator== (Symbol sy1, Symbol sy2)
|
||||
{
|
||||
return sy1.c() == sy2.c();
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!= (Symbol sy1, Symbol sy2)
|
||||
{
|
||||
return not (sy1 == sy2);
|
||||
}
|
||||
|
||||
|
||||
/// mixed comparison based on string equality
|
||||
inline bool
|
||||
operator== (Symbol sy1, Literal sy2)
|
||||
{
|
||||
return Literal(sy1) == sy2;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator== (Literal sy1, Symbol sy2)
|
||||
{
|
||||
return sy1 == Literal(sy2);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!= (Symbol sy1, Literal sy2)
|
||||
{
|
||||
return not (sy1 == sy2);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!= (Literal sy1, Symbol sy2)
|
||||
{
|
||||
return not (sy1 == sy2);
|
||||
}
|
||||
|
||||
|
||||
/// comparison with c-strings //////TICKET #417
|
||||
inline bool
|
||||
operator== (Literal sy1, const char* const sy2)
|
||||
operator== (Literal sy1, const char* sy2)
|
||||
{
|
||||
return (sy1 == Literal(sy2));
|
||||
return (sy1 == Literal(sy2));
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator== (const char* const sy1, Literal sy2)
|
||||
operator== (const char* sy1, Literal sy2)
|
||||
{
|
||||
return (Literal(sy1) == sy2);
|
||||
return (Literal(sy1) == sy2);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!= (Literal sy1, const char* const sy2)
|
||||
operator!= (Literal sy1, const char* sy2)
|
||||
{
|
||||
return ! (sy1 == Literal(sy2));
|
||||
return ! (sy1 == Literal(sy2));
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!= (const char* const sy1, Literal sy2)
|
||||
operator!= (const char* sy1, Literal sy2)
|
||||
{
|
||||
return ! (Literal(sy1) == sy2);
|
||||
return ! (Literal(sy1) == sy2);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator== (Symbol sy1, const char* sy2)
|
||||
{
|
||||
return (Literal(sy1) == Literal(sy2));
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator== (const char* sy1, Symbol sy2)
|
||||
{
|
||||
return (Literal(sy1) == Literal(sy2));
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!= (Symbol sy1, const char* sy2)
|
||||
{
|
||||
return ! (Literal(sy1) == Literal(sy2));
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!= (const char* sy1, Symbol sy2)
|
||||
{
|
||||
return ! (Literal(sy1) == Literal(sy2));
|
||||
}
|
||||
|
||||
/// string concatenation
|
||||
|
|
@ -188,18 +245,7 @@ namespace lib {
|
|||
return symP + str;
|
||||
}
|
||||
|
||||
/* ===== temporary symbol table workaround ===== */
|
||||
|
||||
/** place the string persistently in memory.
|
||||
* @todo temporary workaround, shall be replaced by lib::Symbol implementation ///////////////TICKET #157 maintain symbol table for interned strings
|
||||
* @return a C-String marked as lib::Symbol, pointing
|
||||
* to the permanent location in heap memory.
|
||||
* @warning eternally growing, please look away...
|
||||
* @see symbol-impl.cpp implementation
|
||||
*/
|
||||
Symbol internedString (std::string&& idString);
|
||||
|
||||
|
||||
} // namespace lib
|
||||
|
||||
#endif
|
||||
#endif /*LIB_SYMBOL_H*/
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ namespace control {
|
|||
Symbol
|
||||
CommandInstanceManager::newInstance (Symbol prototypeID, string invocationID)
|
||||
{
|
||||
Symbol instanceID{lib::internedString (string{prototypeID}+"."+invocationID)};
|
||||
Symbol instanceID{prototypeID, invocationID};
|
||||
Command& instance = table_[instanceID];
|
||||
if (instance)
|
||||
throw new error::Logic (_Fmt{"Attempt to create a new Command instance '%s', "
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ namespace test{
|
|||
fabricateNewInstance (lib::test::EventLog const& invocationLog)
|
||||
{
|
||||
log_ = invocationLog;
|
||||
return proc::control::CommandDef(lib::internedString (uniqueTypeInstance()))
|
||||
return proc::control::CommandDef{Symbol{uniqueTypeInstance()}}
|
||||
.operation(PlaceholderCommand::operate)
|
||||
.captureUndo(PlaceholderCommand::capture)
|
||||
.undoOperation(PlaceholderCommand::undo);
|
||||
|
|
|
|||
|
|
@ -111,18 +111,25 @@ namespace test{
|
|||
Symbol sy2(l1);
|
||||
|
||||
CHECK (sy1 == sy2);
|
||||
CHECK (!isSameObject (l1,sy1));
|
||||
CHECK (!isSameObject (sy1,sy2));
|
||||
CHECK (not isSameObject (l1,sy1));
|
||||
CHECK (not isSameObject (sy1,sy2));
|
||||
CHECK (l1.c() == sy1.c());
|
||||
CHECK (sy1.c() == sy2.c());
|
||||
|
||||
Symbol sy3;
|
||||
CHECK (isnil(sy3));
|
||||
CHECK (sy1 != sy3);
|
||||
|
||||
sy3 = l1;
|
||||
sy3 = Symbol{l1};
|
||||
CHECK (!isnil(sy3));
|
||||
CHECK (sy1 == sy3);
|
||||
|
||||
TODO ("real functionality of Symbol data type");
|
||||
Symbol sy4{sy3, "11"};
|
||||
CHECK (sy4 == "1.11");
|
||||
CHECK (not isSameObject(sy4.c(), "1.11"));
|
||||
CHECK (sy4.c() == Symbol{"1.11"}.c());
|
||||
CHECK (sy4.c() == (const char*)sy4);
|
||||
CHECK (hash_value(sy4) == hash_value(Symbol{"1.11"}));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue