netgen/libsrc/core/symboltable.hpp
2019-01-02 18:21:52 +01:00

145 lines
3.6 KiB
C++

#ifndef NETGEN_CORE_SYMBOLTABLE_HPP
#define NETGEN_CORE_SYMBOLTABLE_HPP
#include <ostream>
#include <string>
#include <vector>
#include "archive.hpp"
#include "exception.hpp"
#include "ngcore_api.hpp"
namespace ngcore
{
/**
A symbol table.
The symboltable provides a mapping from string identifiers
to the generic type T. The strings are copied.
Complexity by name access is linear, by index is constant.
*/
template <class T>
class NGCORE_API SymbolTable
{
std::vector<std::string> names;
std::vector<T> data;
public:
using value_type = T;
using reference = typename std::vector<T>::reference;
using const_reference = typename std::vector<T>::const_reference;
/// Creates a symboltable
SymbolTable () = default;
SymbolTable (const SymbolTable<T> &) = default;
SymbolTable (SymbolTable<T> &&) noexcept = default;
~SymbolTable() = default;
SymbolTable& operator=(const SymbolTable<T>&) = default;
SymbolTable& operator=(SymbolTable<T>&&) = default;
template<typename T2=T>
auto DoArchive(Archive& ar) -> typename std::enable_if<is_archivable<T2>, void>::type
{
ar & names & data;
}
/// INDEX of symbol name, throws exception if unused
NGCORE_API size_t Index (const std::string & name) const
{
for (size_t i = 0; i < names.size(); i++)
if (names[i] == name) return i;
throw RangeException("SymbolTable", name);
}
/// Index of symbol name, returns -1 if unused
NGCORE_API int CheckIndex (const std::string & name) const
{
for (int i = 0; i < names.size(); i++)
if (names[i] == name) return i;
return -1;
}
/// number of identifiers
size_t Size() const
{
return data.size();
}
/// Returns reference to element. exception for unused identifier
reference operator[] (const std::string & name)
{
return data[Index (name)];
}
const_reference operator[] (const std::string & name) const
{
return data[Index (name)];
}
/// Returns reference to i-th element, range check only in debug build
reference operator[] (size_t i)
{
NETGEN_CHECK_RANGE(i, 0, data.size());
return data[i];
}
/// Returns const reference to i-th element, range check only in debug build
const_reference operator[] (size_t i) const
{
NETGEN_CHECK_RANGE(i, 0, data.size());
return data[i];
}
/// Returns name of i-th element, range check only in debug build
const std::string & GetName (size_t i) const
{
NETGEN_CHECK_RANGE(i, 0, names.size());
return names[i];
}
/// Associates el to the string name, overrides if name is used
void Set (const std::string & name, const T & el)
{
int i = CheckIndex (name);
if (i >= 0)
data[i] = el;
else
{
data.push_back(el);
names.push_back(name);
}
}
bool Used (const std::string & name) const
{
return CheckIndex(name) >= 0;
}
/// Deletes symboltable
inline void DeleteAll ()
{
names.clear();
data.clear();
}
// Adds all elements from other symboltable
SymbolTable<T>& Update(const SymbolTable<T>& tbl2)
{
for (size_t i = 0; i < tbl2.Size(); i++)
Set (tbl2.GetName(i), tbl2[i]);
return *this;
}
};
template <typename T>
std::ostream & operator<< (std::ostream & ost, const SymbolTable<T> & st)
{
for (int i = 0; i < st.Size(); i++)
ost << st.GetName(i) << " : " << st[i] << std::endl;
return ost;
}
} // namespace ngcore
#endif // NETGEN_CORE_SYMBOLTABLE_HPP