move SymbolTable to ngcore

This commit is contained in:
Christopher Lackner 2019-01-02 18:21:52 +01:00
parent a4f4b6c1be
commit f88cc77cfe
19 changed files with 299 additions and 278 deletions

View File

@ -32,7 +32,7 @@ if(USE_PYTHON)
endif(USE_PYTHON)
install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp
exception.hpp
exception.hpp symboltable.hpp
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel)
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)

View File

@ -205,6 +205,34 @@ namespace ngcore
Do(&v[0], size);
return (*this);
}
// vector<bool> has special implementation (like a bitarray) therefore
// it needs a special overload (this could probably be more efficient, but we
// don't use it that often anyway)
template<>
Archive& operator& (std::vector<bool>& v)
{
size_t size;
if(Output())
size = v.size();
(*this) & size;
if(Input())
{
v.resize(size);
bool b;
for(size_t i=0; i<size; i++)
{
(*this) & b;
v[i] = b;
}
}
else
{
for(bool b : v)
(*this) & b;
}
return *this;
}
template<typename T1, typename T2>
Archive& operator& (std::map<T1, T2>& map)
{

View File

@ -4,6 +4,7 @@
#include "archive.hpp"
#include "exception.hpp"
#include "logging.hpp"
#include "symboltable.hpp"
#include "version.hpp"
#endif // NETGEN_CORE_NGCORE_HPP

144
libsrc/core/symboltable.hpp Normal file
View File

@ -0,0 +1,144 @@
#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

View File

@ -562,7 +562,7 @@ namespace netgen
const Surface * CSGeometry :: GetSurface (const char * name) const
{
if (surfaces.Used(name))
return surfaces.Get(name);
return surfaces[name];
else
return NULL;
}
@ -585,7 +585,7 @@ namespace netgen
Solid * oldsol = NULL;
if (solids.Used (name))
oldsol = solids.Get(name);
oldsol = solids[name];
solids.Set (name, sol);
sol->SetName (name);
@ -605,7 +605,7 @@ namespace netgen
const Solid * CSGeometry :: GetSolid (const char * name) const
{
if (solids.Used(name))
return solids.Get(name);
return solids[name];
else
return NULL;
}
@ -616,8 +616,8 @@ namespace netgen
const Solid * CSGeometry :: GetSolid (const string & name) const
{
if (solids.Used(name.c_str()))
return solids.Get(name.c_str());
if (solids.Used(name))
return solids[name];
else
return NULL;
}
@ -637,15 +637,15 @@ namespace netgen
const SplineGeometry<2> * CSGeometry :: GetSplineCurve2d (const string & name) const
{
if (splinecurves2d.Used(name.c_str()))
return splinecurves2d.Get(name.c_str());
if (splinecurves2d.Used(name))
return splinecurves2d[name];
else
return NULL;
}
const SplineGeometry<3> * CSGeometry :: GetSplineCurve3d (const string & name) const
{
if (splinecurves3d.Used(name.c_str()))
return splinecurves3d.Get(name.c_str());
if (splinecurves3d.Used(name))
return splinecurves3d[name];
else
return NULL;
}
@ -721,7 +721,7 @@ namespace netgen
void CSGeometry :: SetFlags (const char * solidname, const Flags & flags)
{
Solid * solid = solids.Elem(solidname);
Solid * solid = solids[solidname];
Array<int> surfind;
int i;

View File

@ -102,7 +102,7 @@ namespace netgen
{
private:
/// all surfaces
SYMBOLTABLE<Surface*> surfaces;
SymbolTable<Surface*> surfaces;
public:
/// primitive of surface
@ -112,12 +112,12 @@ namespace netgen
Array<Surface*> delete_them;
/// all named solids
SYMBOLTABLE<Solid*> solids;
SymbolTable<Solid*> solids;
/// all 2d splinecurves
SYMBOLTABLE< SplineGeometry<2>* > splinecurves2d;
SymbolTable< SplineGeometry<2>* > splinecurves2d;
/// all 3d splinecurves
SYMBOLTABLE< SplineGeometry<3>* > splinecurves3d;
SymbolTable< SplineGeometry<3>* > splinecurves3d;
/// all top level objects: solids and surfaces
Array<TopLevelObject*> toplevelobjects;
@ -203,7 +203,7 @@ namespace netgen
const Solid * GetSolid (const string & name) const;
int GetNSolids () const { return solids.Size(); }
const Solid * GetSolid (int i) const { return solids[i]; }
const SYMBOLTABLE<Solid*> & GetSolids () const { return solids; }
const SymbolTable<Solid*> & GetSolids () const { return solids; }
void SetSplineCurve (const char * name, SplineGeometry<2> * spl);

View File

@ -419,9 +419,9 @@ namespace netgen
static Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE<Solid*> & solids);
static Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE<Solid*> & solids);
static Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE<Solid*> & solids);
static Solid * CreateSolidExpr (istream & ist, const SymbolTable<Solid*> & solids);
static Solid * CreateSolidTerm (istream & ist, const SymbolTable<Solid*> & solids);
static Solid * CreateSolidPrim (istream & ist, const SymbolTable<Solid*> & solids);
static void ReadString (istream & ist, char * str)
{
@ -461,7 +461,7 @@ namespace netgen
}
Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE<Solid*> & solids)
Solid * CreateSolidExpr (istream & ist, const SymbolTable<Solid*> & solids)
{
// cout << "create expr" << endl;
@ -484,7 +484,7 @@ namespace netgen
return s1;
}
Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE<Solid*> & solids)
Solid * CreateSolidTerm (istream & ist, const SymbolTable<Solid*> & solids)
{
// cout << "create term" << endl;
@ -508,7 +508,7 @@ namespace netgen
return s1;
}
Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE<Solid*> & solids)
Solid * CreateSolidPrim (istream & ist, const SymbolTable<Solid*> & solids)
{
Solid * s1;
char ch;
@ -533,7 +533,7 @@ namespace netgen
}
(*testout) << "get terminal " << str << endl;
s1 = solids.Get(str);
s1 = solids[str];
if (s1)
{
// cout << "primitive: " << str << endl;
@ -545,7 +545,7 @@ namespace netgen
}
Solid * Solid :: CreateSolid (istream & ist, const SYMBOLTABLE<Solid*> & solids)
Solid * Solid :: CreateSolid (istream & ist, const SymbolTable<Solid*> & solids)
{
Solid * nsol = CreateSolidExpr (ist, solids);
nsol = new Solid (ROOT, nsol);

View File

@ -158,7 +158,7 @@ namespace netgen
{ return maxh; }
void GetSolidData (ostream & ost, int first = 1) const;
static Solid * CreateSolid (istream & ist, const SYMBOLTABLE<Solid*> & solids);
static Solid * CreateSolid (istream & ist, const SymbolTable<Solid*> & solids);
static BlockAllocator ball;

View File

@ -2,7 +2,7 @@ add_definitions(-DNGINTERFACE_EXPORTS)
add_library(gen OBJECT
array.cpp bitarray.cpp dynamicmem.cpp flags.cpp
hashtabl.cpp mystring.cpp ngexception.cpp optmem.cpp parthreads.cpp
profiler.cpp seti.cpp sort.cpp spbita2d.cpp symbolta.cpp table.cpp
profiler.cpp seti.cpp sort.cpp spbita2d.cpp table.cpp
mpi_interface.cpp gzstream.cpp
)
@ -19,7 +19,7 @@ install(FILES
dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp
ngsimd.hpp mystring.hpp netgenout.hpp ngexception.hpp ngpython.hpp
optmem.hpp parthreads.hpp profiler.hpp seti.hpp sort.hpp
spbita2d.hpp stack.hpp symbolta.hpp table.hpp template.hpp
spbita2d.hpp stack.hpp table.hpp template.hpp
gzstream.h
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel
)

View File

@ -83,7 +83,7 @@ namespace netgen
Flags :: GetStringFlag (const char * name, const char * def) const
{
if (strflags.Used (name))
return strflags.Get(name);
return strflags[name];
else
return def;
}
@ -91,7 +91,7 @@ namespace netgen
double Flags :: GetNumFlag (const char * name, double def) const
{
if (numflags.Used (name))
return numflags.Get(name);
return numflags[name];
else
return def;
}
@ -99,7 +99,7 @@ namespace netgen
const double * Flags :: GetNumFlagPtr (const char * name) const
{
if (numflags.Used (name))
return & ((SYMBOLTABLE<double>&)numflags).Elem(name);
return & ((SymbolTable<double>&)numflags)[name];
else
return NULL;
}
@ -107,7 +107,7 @@ namespace netgen
double * Flags :: GetNumFlagPtr (const char * name)
{
if (numflags.Used (name))
return & ((SYMBOLTABLE<double>&)numflags).Elem(name);
return & ((SymbolTable<double>&)numflags)[name];
else
return NULL;
}
@ -122,7 +122,7 @@ namespace netgen
Flags :: GetStringListFlag (const char * name) const
{
if (strlistflags.Used (name))
return *strlistflags.Get(name);
return *strlistflags[name];
else
{
static Array<char*> dummy_array(0);
@ -134,7 +134,7 @@ namespace netgen
Flags ::GetNumListFlag (const char * name) const
{
if (numlistflags.Used (name))
return *numlistflags.Get(name);
return *numlistflags[name];
else
{
static Array<double> dummy_array(0);
@ -170,9 +170,9 @@ namespace netgen
ofstream outfile (filename);
for (i = 1; i <= strflags.Size(); i++)
outfile << strflags.GetName(i) << " = " << strflags.Get(i) << endl;
outfile << strflags.GetName(i) << " = " << strflags[i] << endl;
for (i = 1; i <= numflags.Size(); i++)
outfile << numflags.GetName(i) << " = " << numflags.Get(i) << endl;
outfile << numflags.GetName(i) << " = " << numflags[i] << endl;
for (i = 1; i <= defflags.Size(); i++)
outfile << defflags.GetName(i) << endl;
}
@ -184,9 +184,9 @@ namespace netgen
int i;
for (i = 1; i <= strflags.Size(); i++)
ost << strflags.GetName(i) << " = " << strflags.Get(i) << endl;
ost << strflags.GetName(i) << " = " << strflags[i] << endl;
for (i = 1; i <= numflags.Size(); i++)
ost << numflags.GetName(i) << " = " << numflags.Get(i) << endl;
ost << numflags.GetName(i) << " = " << numflags[i] << endl;
for (i = 1; i <= defflags.Size(); i++)
ost << defflags.GetName(i) << endl;
}

View File

@ -19,15 +19,15 @@ namespace netgen
class Flags
{
///
SYMBOLTABLE<char *> strflags;
SymbolTable<char *> strflags;
///
SYMBOLTABLE<double> numflags;
SymbolTable<double> numflags;
///
SYMBOLTABLE<int> defflags;
SymbolTable<int> defflags;
///
SYMBOLTABLE<Array<char*>*> strlistflags;
SymbolTable<Array<char*>*> strlistflags;
///
SYMBOLTABLE<Array<double>*> numlistflags;
SymbolTable<Array<double>*> numlistflags;
public:
///
DLL_HEADER Flags ();

View File

@ -33,7 +33,6 @@ namespace netgen
#include "hashtabl.hpp"
#include "symbolta.hpp"
#include "bitarray.hpp"
#include "flags.hpp"
#include "spbita2d.hpp"

View File

@ -1,52 +0,0 @@
/**************************************************************************/
/* File: symbolta.cc */
/* Author: Joachim Schoeberl */
/* Date: 01. Jun. 95 */
/**************************************************************************/
/*
Abstract data type Symbol Table
*/
#include <mystdlib.h>
#include <myadt.hpp>
#ifndef FILE_SYMBOLTABLECC
#define FILE_SYMBOLTABLECC
// necessary for SGI ????
namespace netgen
{
//using namespace netgen;
BASE_SYMBOLTABLE :: BASE_SYMBOLTABLE ()
{
;
}
BASE_SYMBOLTABLE :: ~BASE_SYMBOLTABLE()
{
DelNames();
}
void BASE_SYMBOLTABLE :: DelNames()
{
for (int i = 0; i < names.Size(); i++)
delete [] names[i];
names.SetSize (0);
}
int BASE_SYMBOLTABLE :: Index (const char * name) const
{
if (!name) return 0;
for (int i = 0; i < names.Size(); i++)
if (strcmp (names[i], name) == 0) return i+1;
return 0;
}
}
#endif

View File

@ -1,163 +0,0 @@
#ifndef FILE_SYMBOLTA
#define FILE_SYMBOLTA
/**************************************************************************/
/* File: symbolta.hh */
/* Author: Joachim Schoeberl */
/* Date: 01. Jun. 95 */
/**************************************************************************/
namespace netgen
{
/**
Base class for the generic SYMBOLTABLE.
An array of identifiers is maintained.
*/
class DLL_HEADER BASE_SYMBOLTABLE
{
protected:
/// identifiers
Array <char*> names;
public:
/// Constructor
BASE_SYMBOLTABLE ();
///
~BASE_SYMBOLTABLE ();
///
void DelNames ();
/// Index of symbol name, returns 0 if not used.
int Index (const char * name) const;
};
/**
Abstract data type Symbol Table.
To a string an value of the generic type T is associated.
The string is not copied into the symbol table class!
*/
template <class T>
class SYMBOLTABLE : public BASE_SYMBOLTABLE
{
private:
/// Associated data
Array <T> data;
public:
/// Creates a symboltable
inline SYMBOLTABLE ();
/// Returns size of symboltable
inline INDEX Size() const;
/// Returns reference to element, error if not used
inline T & Elem (const char * name);
/// Returns reference to i-th element
inline T & Elem (int i)
{ return data.Elem(i); }
/// Returns element, error if not used
inline const T & Get (const char * name) const;
/// Returns i-th element
inline const T & Get (int i) const;
/// Returns name of i-th element
inline const char* GetName (int i) const;
/// Associates el to the string name, overrides if name is used
inline void Set (const char * name, const T & el);
/// Checks whether name is used
inline bool Used (const char * name) const;
/// Deletes symboltable
inline void DeleteAll ();
void DoArchive(Archive& archive) { archive & names & data;}
inline T & operator[] (int i)
{ return data[i]; }
inline const T & operator[] (int i) const
{ return data[i]; }
private:
/// Prevents from copying symboltable by pointer assignment
SYMBOLTABLE<T> & operator= (SYMBOLTABLE<T> &);
};
template <class T>
inline SYMBOLTABLE<T> :: SYMBOLTABLE ()
{
;
}
template <class T>
inline INDEX SYMBOLTABLE<T> :: Size() const
{
return data.Size();
}
template <class T>
inline T & SYMBOLTABLE<T> :: Elem (const char * name)
{
int i = Index (name);
if (i)
return data.Elem (i);
else
return data.Elem(1);
}
template <class T>
inline const T & SYMBOLTABLE<T> :: Get (const char * name) const
{
int i;
i = Index (name);
if (i)
return data.Get(i);
else
return data.Get(1);
}
template <class T>
inline const T & SYMBOLTABLE<T> :: Get (int i) const
{
return data.Get(i);
}
template <class T>
inline const char* SYMBOLTABLE<T> :: GetName (int i) const
{
return names.Get(i);
}
template <class T>
inline void SYMBOLTABLE<T> :: Set (const char * name, const T & el)
{
int i;
i = Index (name);
if (i)
data.Set(i, el);
else
{
data.Append (el);
char * hname = new char [strlen (name) + 1];
strcpy (hname, name);
names.Append (hname);
}
}
template <class T>
inline bool SYMBOLTABLE<T> :: Used (const char * name) const
{
return (Index(name)) ? true : false;
}
template <class T>
inline void SYMBOLTABLE<T> :: DeleteAll ()
{
DelNames();
data.DeleteAll();
}
}
#endif

View File

@ -6016,7 +6016,7 @@ namespace netgen
void Mesh :: SetUserData(const char * id, Array<int> & data)
{
if(userdata_int.Used(id))
delete userdata_int.Get(id);
delete userdata_int[id];
Array<int> * newdata = new Array<int>(data);
@ -6026,10 +6026,10 @@ namespace netgen
{
if(userdata_int.Used(id))
{
if(data.Size() < (*userdata_int.Get(id)).Size()+shift)
data.SetSize((*userdata_int.Get(id)).Size()+shift);
for(int i=0; i<(*userdata_int.Get(id)).Size(); i++)
data[i+shift] = (*userdata_int.Get(id))[i];
if(data.Size() < (*userdata_int[id]).Size()+shift)
data.SetSize((*userdata_int[id]).Size()+shift);
for(int i=0; i<(*userdata_int[id]).Size(); i++)
data[i+shift] = (*userdata_int[id])[i];
return true;
}
else
@ -6041,7 +6041,7 @@ namespace netgen
void Mesh :: SetUserData(const char * id, Array<double> & data)
{
if(userdata_double.Used(id))
delete userdata_double.Get(id);
delete userdata_double[id];
Array<double> * newdata = new Array<double>(data);
@ -6051,10 +6051,10 @@ namespace netgen
{
if(userdata_double.Used(id))
{
if(data.Size() < (*userdata_double.Get(id)).Size()+shift)
data.SetSize((*userdata_double.Get(id)).Size()+shift);
for(int i=0; i<(*userdata_double.Get(id)).Size(); i++)
data[i+shift] = (*userdata_double.Get(id))[i];
if(data.Size() < (*userdata_double[id]).Size()+shift)
data.SetSize((*userdata_double[id]).Size()+shift);
for(int i=0; i<(*userdata_double[id]).Size(); i++)
data[i+shift] = (*userdata_double[id])[i];
return true;
}
else

View File

@ -132,8 +132,8 @@ namespace netgen
/// mesh access semaphors.
NgMutex majormutex;
SYMBOLTABLE< Array<int>* > userdata_int;
SYMBOLTABLE< Array<double>* > userdata_double;
SymbolTable< Array<int>* > userdata_int;
SymbolTable< Array<double>* > userdata_double;
mutable Array< Point3d > pointcurves;

View File

@ -1840,9 +1840,9 @@ namespace netgen
SYMBOLTABLE<VisualScene*> & GetVisualizationScenes ()
SymbolTable<VisualScene*> & GetVisualizationScenes ()
{
static SYMBOLTABLE<VisualScene*> vss;
static SymbolTable<VisualScene*> vss;
return vss;
}
@ -1860,7 +1860,7 @@ namespace netgen
vs = &vscross;
if (GetVisualizationScenes().Used(vismode))
{
vs = GetVisualizationScenes().Get(vismode);
vs = GetVisualizationScenes()[vismode];
}
else if (vismode)
{

View File

@ -19,14 +19,14 @@ macro(add_unit_test name sources)
add_dependencies(unit_tests test_${name})
add_test(NAME unit_${name} COMMAND test_${name})
set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built)
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
set_target_properties(test_${name} PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
endmacro()
add_unit_test(archive archive.cpp)
add_unit_test(symboltable symboltable.cpp)
add_unit_test(version version.cpp)
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
set_target_properties(test_archive PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
set_target_properties(test_version PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
endif(ENABLE_UNIT_TESTS)

View File

@ -0,0 +1,64 @@
#include "catch.hpp"
#include <../core/ngcore.hpp>
using namespace ngcore;
using namespace std;
TEST_CASE("Symboltable")
{
SymbolTable<int> table;
CHECK_THROWS_AS(table["test"], RangeException);
table.Set("first", 1);
CHECK(table["first"] == 1);
table["first"] = 2;
CHECK(table["first"] == 2);
auto index = table.Index("first");
CHECK(index == 0);
CHECK(table[index] == 2);
table[index] = 3;
CHECK(table["first"] == 3);
#ifndef NDEBUG
int a;
CHECK_THROWS_AS(a = table[5], RangeException);
CHECK_THROWS_AS(table.GetName(5), RangeException);
#endif
CHECK(table.Used("first"));
CHECK(!table.Used("second"));
SymbolTable<int> another;
another.Set("first", 1);
another.Set("second", 2);
table.Update(another);
CHECK(table["first"] == 1);
CHECK(table["second"] == 2);
std::stringstream s;
s << table;
CHECK(s.str() == "first : 1\nsecond : 2\n");
auto ss = std::make_shared<std::stringstream>();
BinaryOutArchive ao(ss);
ao & table;
ao.FlushBuffer();
BinaryInArchive ai(ss);
SymbolTable<int> read;
ai & read;
for(size_t i = 0; i<table.Size(); i++)
{
CHECK(read[i] == table[i]);
CHECK(read.GetName(i) == table.GetName(i));
}
table.DeleteAll();
CHECK(table.Size() == 0);
// SymbolTable<bool> is special because of vector<bool> is special...
SymbolTable<bool> btable;
btable.Set("true", true);
btable.Set("false", false);
CHECK(btable[0]);
CHECK(!btable[1]);
CHECK(btable["true"]);
CHECK(!btable["false"]);
ao & btable;
ao.FlushBuffer();
SymbolTable<bool> bread;
ai & bread;
CHECK(bread["true"]);
CHECK(!bread["false"]);
}