LUMIERA.clone/src/lib/symbol.hpp
Ichthyostega 2204066a94 Symbol: test coverage for empty and bool
oh yeah
yet another opportunity for mistakes
2017-04-07 20:06:19 +02:00

195 lines
6.6 KiB
C++

/*
SYMBOL.hpp - symbolic constant datatype
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file symbol.hpp
** WIP placeholder definition for a planned Symbol datatype.
**
** @todo for the (currently just planned as of 11/08) rules based configuration
** in the Proc-Layer a explicit Symbol datatype will probably very helpful.
** For now just a typedef is sufficient. A real Symbol datatype should
** - be definable by string constant
** - integrate smoothly with std::string
** - provide a unique numeric index for each distinct Symbol
** - automatically maintain a symbol table at runtime to support this
** - provide some magic (macros) allowing to build distinct types based on symbols.
**
** @see symbol-impl.cpp
** @see configrules.hpp
** @see query.hpp
*/
#ifndef LIB_SYMBOL_H
#define LIB_SYMBOL_H
#include "lib/hash-standard.hpp"
#include "include/logging.h" /////////////TODO only temporarily
#include <string>
#include <cstring>
namespace lib {
/** inline string literal
* @todo improve interaction with Symbol
* @todo make it non-nullable
* @todo maybe use boost/operators Ticket #417
*/
class Literal
{
const char * str_;
public:
Literal (const char* literal)
: str_(literal)
{ }
Literal (Literal const& o)
: str_(o.str_)
{ }
operator const char* () const { return str_; }
const char* c() const { return str_; }
bool
empty() const
{
return !str_ || 0 == std::strlen(str_);
}
bool operator== (const char* cString) const;
protected:
/** Assignment prohibited */
Literal& operator= (const char* newStr)
{
str_ = newStr;
return *this;
}
};
/** Token or Atom with distinct identity
* @note same literal string==same pointer representation
*/
class Symbol
: public Literal
{
public:
static Symbol BOTTOM;
static Symbol FAILURE;
Symbol (const char* lit =NULL)
: Symbol{std::string(lit? lit : BOTTOM.c())}
{ }
explicit
Symbol (std::string&& definition);
Symbol (std::string const& str)
: Symbol{std::string(str)}
{ }
Symbol (Literal const& base, std::string ext)
: Symbol{std::string(base)+"."+ext}
{ }
Symbol (Literal const& base, const char* ext)
: Symbol{base, std::string(ext)}
{ }
Symbol (Symbol const&) = default;
Symbol (Symbol &&) = default;
Symbol& operator= (Symbol const&) = default;
Symbol& operator= (Symbol &&) = default;
explicit operator bool() const { return not empty(); }
bool empty() const { return *this == BOTTOM; }
};
/** safety guard: maximum number of chars to process.
* For comparisons, hash calculations etc., when dealing
* with raw char ptrs (typically literal values) */
extern const size_t STRING_MAX_RELEVANT;
/* ===== to be picked up by ADL ===== */
size_t hash_value (Literal);
/* === equality comparisons === */
inline bool operator== (Literal const& s1, Literal const& s2) { return s1.operator== (s2.c()); }
inline bool operator== (Symbol const& s1, Symbol const& s2) { return s1.c() == s2.c(); } ///< @note comparison of symbol table entries
/* === mixed comparisons === */
inline bool operator== (const char* s1, Literal s2) { return s2.operator== (s1); }
inline bool operator== (Symbol s1, const char* s2) { return s1.operator== (s2); }
inline bool operator== (const char* s1, Symbol s2) { return s2.operator== (s1); }
inline bool operator== (Literal s1, Symbol s2) { return s1.operator== (s2.c()); }
inline bool operator== (Symbol s1, Literal s2) { return s2.operator== (s1.c()); }
inline bool operator== (Literal s1, std::string s2) { return s1.operator== (s2.c_str()); }
inline bool operator== (std::string s1, Literal s2) { return s2.operator== (s1.c_str()); }
inline bool operator== (Symbol s1, std::string s2) { return s1.operator== (s2.c_str()); }
inline bool operator== (std::string s1, Symbol s2) { return s2.operator== (s1.c_str()); }
/* === negations === */
inline bool operator!= (Literal const& s1, Literal const& s2) { return not s1.operator== (s2.c()); }
inline bool operator!= (Symbol const& s1, Symbol const& s2) { return not (s1.c() == s2.c()); }
inline bool operator!= (Literal s1, const char* s2) { return not s1.operator== (s2); }
inline bool operator!= (const char* s1, Literal s2) { return not s2.operator== (s1); }
inline bool operator!= (Symbol s1, const char* s2) { return not s1.operator== (s2); }
inline bool operator!= (const char* s1, Symbol s2) { return not s2.operator== (s1); }
inline bool operator!= (Literal s1, Symbol s2) { return not s1.operator== (s2.c()); }
inline bool operator!= (Symbol s1, Literal s2) { return not s2.operator== (s1.c()); }
inline bool operator!= (Literal s1, std::string s2) { return not s1.operator== (s2.c_str()); }
inline bool operator!= (std::string s1, Literal s2) { return not s2.operator== (s1.c_str()); }
inline bool operator!= (Symbol s1, std::string s2) { return not s1.operator== (s2.c_str()); }
inline bool operator!= (std::string s1, Symbol s2) { return not s2.operator== (s1.c_str()); }
/// string concatenation
inline std::string
operator+ (std::string str, Literal const& sym)
{
const char* symP (sym);
return str + symP;
}
inline std::string
operator+ (Literal const& sym, std::string str)
{
const char* symP (sym);
return symP + str;
}
} // namespace lib
#endif /*LIB_SYMBOL_H*/