diff --git a/src/lib/symbol-impl.cpp b/src/lib/symbol-impl.cpp index 529255b3c..e677fc7d5 100644 --- a/src/lib/symbol-impl.cpp +++ b/src/lib/symbol-impl.cpp @@ -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 symbolTable; ////////////////////////////////TICKET #158 replace by symbol table + std::unordered_set 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 (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 (definition)).first->c_str()} + { } diff --git a/src/lib/symbol.hpp b/src/lib/symbol.hpp index 2c96dc8d1..b6356f322 100644 --- a/src/lib/symbol.hpp +++ b/src/lib/symbol.hpp @@ -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*/ diff --git a/src/proc/control/command-setup.cpp b/src/proc/control/command-setup.cpp index d4feb65ef..7545c9c0b 100644 --- a/src/proc/control/command-setup.cpp +++ b/src/proc/control/command-setup.cpp @@ -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', " diff --git a/tests/gui/test/placeholder-command.hpp b/tests/gui/test/placeholder-command.hpp index dc8313d3a..0cd1593e4 100644 --- a/tests/gui/test/placeholder-command.hpp +++ b/tests/gui/test/placeholder-command.hpp @@ -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); diff --git a/tests/library/symbol-test.cpp b/tests/library/symbol-test.cpp index c0f4168aa..8392a72cc 100644 --- a/tests/library/symbol-test.cpp +++ b/tests/library/symbol-test.cpp @@ -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"})); } };