From 3902456b3b8a902cdcf2fa491aa18612aa2e4c94 Mon Sep 17 00:00:00 2001 From: lorenz Date: Tue, 27 Nov 2018 16:23:47 +0100 Subject: [PATCH 01/46] build without gui shouldn't add visualization for occ --- libsrc/occ/CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libsrc/occ/CMakeLists.txt b/libsrc/occ/CMakeLists.txt index 2f10e54e..c9d6b880 100644 --- a/libsrc/occ/CMakeLists.txt +++ b/libsrc/occ/CMakeLists.txt @@ -4,13 +4,16 @@ add_library(occ ${NG_LIB_TYPE} Partition_Loop.cxx Partition_Loop2d.cxx Partition_Loop3d.cxx Partition_Spliter.cxx occconstruction.cpp occgenmesh.cpp occgeom.cpp occmeshsurf.cpp python_occ.cpp ) - -add_library(occvis ${NG_LIB_TYPE} vsocc.cpp) +if(USE_GUI) + add_library(occvis ${NG_LIB_TYPE} vsocc.cpp) +endif(USE_GUI) if(NOT WIN32) target_link_libraries( occ ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) - target_link_libraries( occvis occ ) - install( TARGETS occ occvis ${NG_INSTALL_DIR}) + if (USE_GUI) + target_link_libraries( occvis occ ) + install( TARGETS occ occvis ${NG_INSTALL_DIR}) + endif(USE_GUI) endif(NOT WIN32) install(FILES From 143218245880f62a0489905c2f38714159089683 Mon Sep 17 00:00:00 2001 From: lorenz Date: Tue, 27 Nov 2018 16:29:07 +0100 Subject: [PATCH 02/46] occ must be installed --- libsrc/occ/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsrc/occ/CMakeLists.txt b/libsrc/occ/CMakeLists.txt index c9d6b880..831a3875 100644 --- a/libsrc/occ/CMakeLists.txt +++ b/libsrc/occ/CMakeLists.txt @@ -10,9 +10,10 @@ endif(USE_GUI) if(NOT WIN32) target_link_libraries( occ ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) + install( TARGETS occ ${NG_INSTALL_DIR}) if (USE_GUI) target_link_libraries( occvis occ ) - install( TARGETS occ occvis ${NG_INSTALL_DIR}) + install( TARGETS occvis ${NG_INSTALL_DIR}) endif(USE_GUI) endif(NOT WIN32) From 593ce091b7234684561ae9e20c12440cd2cb7c30 Mon Sep 17 00:00:00 2001 From: lorenz Date: Thu, 29 Nov 2018 15:51:20 +0100 Subject: [PATCH 03/46] link to visual also if USE_GUI=OFF --- libsrc/interface/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libsrc/interface/CMakeLists.txt b/libsrc/interface/CMakeLists.txt index ef52c30b..cb460fae 100644 --- a/libsrc/interface/CMakeLists.txt +++ b/libsrc/interface/CMakeLists.txt @@ -9,9 +9,7 @@ add_library(interface ${NG_LIB_TYPE} if(NOT WIN32) target_link_libraries(interface mesh csg geom2d) - if(USE_GUI) - target_link_libraries(interface visual) - endif(USE_GUI) + target_link_libraries(interface visual) install( TARGETS interface ${NG_INSTALL_DIR}) endif(NOT WIN32) From 7bfc48e8f368130dc75f8db55d00857badc609dd Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Thu, 29 Nov 2018 18:35:30 +0100 Subject: [PATCH 04/46] start ngcore, archive in there --- CMakeLists.txt | 2 +- libsrc/CMakeLists.txt | 1 + libsrc/core/CMakeLists.txt | 8 + libsrc/core/archive.hpp | 218 +++++++++++++++++++++++ libsrc/core/basearchive.cpp | 11 ++ libsrc/core/basearchive.hpp | 266 ++++++++++++++++++++++++++++ libsrc/core/ngcore.hpp | 30 ++++ libsrc/csg/csgeom.cpp | 6 + libsrc/csg/csgeom.hpp | 7 + libsrc/csg/python_csg.cpp | 57 +++--- libsrc/csg/surface.hpp | 22 ++- libsrc/general/CMakeLists.txt | 2 +- libsrc/general/archive_base.hpp | 144 --------------- libsrc/general/array.hpp | 37 ++-- libsrc/general/hashtabl.hpp | 20 +-- libsrc/general/myadt.hpp | 6 +- libsrc/general/symbolta.hpp | 2 + libsrc/general/table.cpp | 3 +- libsrc/general/table.hpp | 14 +- libsrc/gprim/geomobjects.hpp | 15 ++ libsrc/include/nginterface_v2.hpp | 2 +- libsrc/interface/nginterface_v2.cpp | 2 +- libsrc/meshing/CMakeLists.txt | 1 + libsrc/meshing/meshclass.cpp | 2 +- libsrc/meshing/meshclass.hpp | 2 +- libsrc/meshing/meshtype.cpp | 11 +- libsrc/meshing/meshtype.hpp | 50 +----- 27 files changed, 653 insertions(+), 288 deletions(-) create mode 100644 libsrc/core/CMakeLists.txt create mode 100644 libsrc/core/archive.hpp create mode 100644 libsrc/core/basearchive.cpp create mode 100644 libsrc/core/basearchive.hpp create mode 100644 libsrc/core/ngcore.hpp delete mode 100644 libsrc/general/archive_base.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ef0ee424..6f4bfd9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,7 +204,7 @@ macro(get_dll_from_lib dll_path lib_path) get_filename_component(lib_name ${lib} name) endmacro() -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) if(WIN32) get_WIN32_WINNT(ver) add_definitions(-D_WIN32_WINNT=${ver} -DWNT -DWNT_WINDOW -DNOMINMAX) diff --git a/libsrc/CMakeLists.txt b/libsrc/CMakeLists.txt index 89dc88a5..eb67d688 100644 --- a/libsrc/CMakeLists.txt +++ b/libsrc/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(core) add_subdirectory(general) add_subdirectory(gprim) add_subdirectory(linalg) diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt new file mode 100644 index 00000000..d49da46b --- /dev/null +++ b/libsrc/core/CMakeLists.txt @@ -0,0 +1,8 @@ +add_definitions(-DNGINTERFACE_EXPORTS) +add_library(ngcore OBJECT basearchive.cpp) + +set_target_properties(ngcore PROPERTIES POSITION_INDEPENDENT_CODE ON ) + +install(FILES ngcore.hpp archive.hpp basearchive.hpp + DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel +) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp new file mode 100644 index 00000000..639102f4 --- /dev/null +++ b/libsrc/core/archive.hpp @@ -0,0 +1,218 @@ +#ifndef NG_ARCHIVE_HPP +#define NG_ARCHIVE_HPP + +namespace ngcore +{ + // BinaryOutArchive ====================================================================== + class BinaryOutArchive : public Archive + { + std::shared_ptr fout; + size_t ptr = 0; + enum { BUFFERSIZE = 1024 }; + char buffer[BUFFERSIZE]; + public: + BinaryOutArchive (std::shared_ptr afout) : Archive(true), fout(afout) { ; } + BinaryOutArchive (std::string filename) + : BinaryOutArchive(std::make_shared(filename)) {} + virtual ~BinaryOutArchive () { FlushBuffer(); } + + virtual Archive & operator & (double & d) + { return Write(d); } + virtual Archive & operator & (int & i) + { return Write(i); } + virtual Archive & operator & (short & i) + { return Write(i); } + virtual Archive & operator & (long & i) + { return Write(i); } + virtual Archive & operator & (size_t & i) + { return Write(i); } + virtual Archive & operator & (unsigned char & i) + { return Write(i); } + virtual Archive & operator & (bool & b) + { return Write(b); } + virtual Archive & operator & (std::string & str) + { + if (ptr > 0) FlushBuffer(); + int len = str.length(); + fout->write (reinterpret_cast(&len), sizeof(int)); + fout->write (&str[0], len); + return *this; + } + virtual Archive & operator & (char *& str) + { + if (ptr > 0) FlushBuffer(); + int len = strlen (str); + fout->write (reinterpret_cast(&len), sizeof(int)); + fout->write (&str[0], len); + return *this; + } + void FlushBuffer() + { + if (ptr > 0) + { + fout->write(&buffer[0], ptr); + ptr = 0; + } + } + + private: + template + Archive & Write (T x) + { + if (unlikely(ptr > BUFFERSIZE-sizeof(T))) + { + fout->write(&buffer[0], ptr); + * (T*) (&buffer[0]) = x; + ptr = sizeof(T); + return *this; + } + * (T*) (&buffer[ptr]) = x; + ptr += sizeof(T); + return *this; + } + }; + + // BinaryInArchive ====================================================================== + class BinaryInArchive : public Archive + { + std::shared_ptr fin; + public: + BinaryInArchive (std::shared_ptr afin) : Archive(false), fin(afin) { ; } + BinaryInArchive (std::string filename) + : BinaryInArchive(std::make_shared(filename)) {} + + virtual Archive & operator & (double & d) + { Read(d); return *this; } + virtual Archive & operator & (int & i) + { Read(i); return *this; } + virtual Archive & operator & (short & i) + { Read(i); return *this; } + virtual Archive & operator & (long & i) + { Read(i); return *this; } + virtual Archive & operator & (size_t & i) + { Read(i); return *this; } + virtual Archive & operator & (unsigned char & i) + { Read(i); return *this; } + virtual Archive & operator & (bool & b) + { Read(b); return *this; } + virtual Archive & operator & (std::string & str) + { + int len; + Read(len); + str.resize(len); + fin->read(&str[0], len); + return *this; + } + virtual Archive & operator & (char *& str) + { + int len; + Read(len); + str = new char[len+1]; + fin->read(&str[0], len); + str[len] = '\0'; + return *this; + } + + virtual Archive & Do (double * d, size_t n) + { fin->read(reinterpret_cast(d), n*sizeof(double)); return *this; } + virtual Archive & Do (int * i, size_t n) + { fin->read(reinterpret_cast(i), n*sizeof(int)); return *this; } + virtual Archive & Do (size_t * i, size_t n) + { fin->read(reinterpret_cast(i), n*sizeof(size_t)); return *this; } + + private: + template + inline void Read(T& val) + { fin->read(reinterpret_cast(&val), sizeof(T)); } + }; + + // TextOutArchive ====================================================================== + class TextOutArchive : public Archive + { + std::shared_ptr fout; + public: + TextOutArchive (std::shared_ptr afout) : Archive(true), fout(afout) { } + TextOutArchive (std::string filename) : + TextOutArchive(std::make_shared(filename.c_str())) { } + + using Archive::operator&; + virtual Archive & operator & (double & d) + { *fout << d << '\n'; return *this; } + virtual Archive & operator & (int & i) + { *fout << i << '\n'; return *this; } + virtual Archive & operator & (short & i) + { *fout << i << '\n'; return *this; } + virtual Archive & operator & (long & i) + { *fout << i << '\n'; return *this; } + virtual Archive & operator & (size_t & i) + { *fout << i << '\n'; return *this; } + virtual Archive & operator & (unsigned char & i) + { *fout << int(i) << '\n'; return *this; } + virtual Archive & operator & (bool & b) + { *fout << (b ? 't' : 'f') << '\n'; return *this; } + virtual Archive & operator & (std::string & str) + { + int len = str.length(); + *fout << len << '\n'; + fout->write(&str[0], len); + *fout << '\n'; + return *this; + } + virtual Archive & operator & (char *& str) + { + int len = strlen (str); + *fout << len << '\n'; + fout->write (&str[0], len); + *fout << '\n'; + return *this; + } + }; + + // TextInArchive ====================================================================== + class TextInArchive : public Archive + { + std::shared_ptr fin; + public: + TextInArchive (std::shared_ptr afin) : Archive(false), fin(afin) { ; } + TextInArchive (std::string filename) + : TextInArchive(std::make_shared(filename)) {} + + using Archive::operator&; + virtual Archive & operator & (double & d) + { *fin >> d; return *this; } + virtual Archive & operator & (int & i) + { *fin >> i; return *this; } + virtual Archive & operator & (short & i) + { *fin >> i; return *this; } + virtual Archive & operator & (long & i) + { *fin >> i; return *this; } + virtual Archive & operator & (size_t & i) + { *fin >> i; return *this; } + virtual Archive & operator & (unsigned char & i) + { int _i; *fin >> _i; i = _i; return *this; } + virtual Archive & operator & (bool & b) + { char c; *fin >> c; b = (c=='t'); return *this; } + virtual Archive & operator & (std::string & str) + { + int len; + *fin >> len; + char ch; + fin->get(ch); // '\n' + str.resize(len); + fin->get(&str[0], len+1, '\0'); + return *this; + } + virtual Archive & operator & (char *& str) + { + int len; + *fin >> len; + char ch; + fin->get(ch); // '\n' + str = new char[len+1]; + fin->get(&str[0], len, '\0'); + str[len] = 0; + return *this; + } + }; +} +#endif // NG_ARCHIVE_HPP diff --git a/libsrc/core/basearchive.cpp b/libsrc/core/basearchive.cpp new file mode 100644 index 00000000..1fcbe8b8 --- /dev/null +++ b/libsrc/core/basearchive.cpp @@ -0,0 +1,11 @@ + +#include "ngcore.hpp" + +namespace ngcore +{ + std::map>& GetArchiveRegister() + { + static std::map> type_register = {}; + return type_register; + } +} diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp new file mode 100644 index 00000000..a43c4bc0 --- /dev/null +++ b/libsrc/core/basearchive.hpp @@ -0,0 +1,266 @@ +#ifndef NG_BASEARCHIVE_HPP +#define NG_BASEARCHIVE_HPP + +namespace ngcore +{ + class Archive; + + // Type trait to check if a class implements a 'void DoArchive(Archive&)' function + template + struct has_DoArchive + { + private: + template + static constexpr auto check(T2*) -> + typename std::is_same().DoArchive(std::declval())),void>::type; + template + static constexpr std::false_type check(...); + typedef decltype(check(0)) type; + public: + static constexpr bool value = type::value; + }; + + std::map>& GetArchiveRegister(); + + // Base Archive class + class Archive + { + bool is_output; + // how many different shared_ptr/pointer have been (un)archived + int shared_ptr_count, ptr_count; + // maps for archived shared pointers and pointers + std::map shared_ptr2nr, ptr2nr; + // vectors for storing the unarchived (shared) pointers + std::vector> nr2shared_ptr; + std::vector nr2ptr; + public: + Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; } + virtual ~Archive() { ; } + + bool Output () { return is_output; } + bool Input () { return !is_output; } + + // Pure virtual functions that have to be implemented by In-/OutArchive + virtual Archive & operator & (double & d) = 0; + virtual Archive & operator & (int & i) = 0; + virtual Archive & operator & (long & i) = 0; + virtual Archive & operator & (size_t & i) = 0; + virtual Archive & operator & (short & i) = 0; + virtual Archive & operator & (unsigned char & i) = 0; + virtual Archive & operator & (bool & b) = 0; + virtual Archive & operator & (std::string & str) = 0; + virtual Archive & operator & (char *& str) = 0; + + + // Archive std classes ================================================ + template + Archive& operator & (std::complex& c) + { + if(is_output) + (*this) << c.real() << c.imag(); + else + { + T tmp; + (*this) & tmp; + c.real(tmp); + (*this) & tmp; + c.imag(tmp); + } + return (*this); + } + template + Archive& operator & (std::vector& v) + { + size_t size; + if(is_output) + size = v.size(); + (*this) & size; + if(!is_output) + v.reserve(size); + Do(&v[0], size); + return (*this); + } + // Archive arrays ===================================================== + template + Archive & Do (T * data, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; + + virtual Archive & Do (double * d, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; + + virtual Archive & Do (int * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + + virtual Archive & Do (long * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + + virtual Archive & Do (size_t * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + + virtual Archive & Do (short * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + + virtual Archive & Do (unsigned char * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + + virtual Archive & Do (bool * b, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; + + // Archive a class implementing a (void DoArchive(Archive&)) method ======= + template::value>> + Archive& operator & (T& val) + { + val.DoArchive(*this); return *this; + } + + // Archive shared_ptrs ================================================= + template + Archive& operator & (std::shared_ptr& ptr) + { + if(Output()) + { + // save -2 for nullptr + if(!ptr) + return (*this) << -2; + auto pos = shared_ptr2nr.find((void*) ptr.get()); + // if not found store -1 and the pointer + if(pos == shared_ptr2nr.end()) + { + shared_ptr2nr[(void*) ptr.get()] = shared_ptr_count++; + auto p = ptr.get(); + return (*this) << -1 & p; + } + // if found store the position + return (*this) << pos->second; + } + else // Input + { + int nr; + (*this) & nr; + if(nr == -2) + ptr = nullptr; + else if (nr == -1) + { + T* p; + (*this) & p; + ptr = std::shared_ptr(p); + nr2shared_ptr.push_back(ptr); + } + else + ptr = std::reinterpret_pointer_cast(nr2shared_ptr[nr]); + } + return *this; + } + + // Archive pointers ======================================================= + template + Archive & operator& (T *& p) + { + if (Output()) + { + // if the pointer is null store -2 + if (!p) + { + int m2 = -2; + (*this) & m2; + return *this; + } + auto pos = ptr2nr.find( (void*) p); + // if the pointer is not found in the map create a new entry + if (pos == ptr2nr.end()) + { + ptr2nr[(void*) p] = ptr_count++; + if(typeid(*p) == typeid(T)) + if constexpr (std::is_constructible::value) + { + return (*this) << -1 & (*p); + } + else + throw std::runtime_error(std::string("Archive error: Class ") + + typeid(*p).name() + " does not provide a default constructor!"); + else + { + // We want this special behaviour only for our classes that implement DoArchive + if constexpr(has_DoArchive::value) + { + if(GetArchiveRegister().count(typeid(*p).name()) == 0) + throw std::runtime_error(std::string("Archive error: Polimorphic type ") + + typeid(*p).name() + + " not registered for archive"); + else + return (*this) << -3 << std::string(typeid(*p).name()) & (*p); + } + else + throw std::runtime_error(std::string("Archive error: Class ") + + typeid(*p).name() + + " is polymorphic but not registered for archiving"); + } + } + else + { + (*this) & pos->second; + } + } + else + { + int nr; + (*this) & nr; + // cout << "in, got nr " << nr << endl; + if (nr == -2) + { + p = nullptr; + } + else if (nr == -1) + { + if constexpr (std::is_constructible::value) + { + p = new T; + // cout << "create new ptr, p = " << p << endl; + (*this) & *p; + nr2ptr.push_back(p); + } + else + throw std::runtime_error("Class isn't registered properly"); + + } + else if(nr == -3) + { + // We want this special behaviour only for our classes that implement DoArchive + if constexpr(has_DoArchive::value) + { + std::string name; + (*this) & name; + p = reinterpret_cast(GetArchiveRegister()[name]()); + nr2ptr.push_back(p); + } + else + throw std::runtime_error("Class isn't registered properly"); + } + else + { + p = (T*)nr2ptr[nr]; + // cout << "reuse ptr " << nr << ": " << p << endl; + } + } + return *this; + } + + // Write a read only variable + template + Archive & operator << (const T & t) + { + T ht(t); + (*this) & ht; + return *this; + } + }; + + template + void RegisterClassForArchive() + { + static_assert(std::is_constructible_v, "Class registered for archive must be default constructible"); + GetArchiveRegister()[std::string(typeid(T).name())] = []() -> void* { return new T; }; + } +} + +#endif // NG_BASEARCHIVE_HPP diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp new file mode 100644 index 00000000..e93a506c --- /dev/null +++ b/libsrc/core/ngcore.hpp @@ -0,0 +1,30 @@ +#ifndef NG_CORE_HPP +#define NG_CORE_HPP + +// std includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined(__GNUC__) + inline bool likely (bool x) { return __builtin_expect((x), true); } + inline bool unlikely (bool x) { return __builtin_expect((x), false); } +#else + inline bool likely (bool x) { return x; } + inline bool unlikely (bool x) { return x; } +#endif + +// own includes +#include "basearchive.hpp" +#include "archive.hpp" + +#endif // NG_CORE_HPP diff --git a/libsrc/csg/csgeom.cpp b/libsrc/csg/csgeom.cpp index 40dda44e..3226e538 100644 --- a/libsrc/csg/csgeom.cpp +++ b/libsrc/csg/csgeom.cpp @@ -324,6 +324,12 @@ namespace netgen } + void CSGeometry :: DoArchive(Archive& archive) + { + archive & surfaces & surf2prim & solids & toplevelobjects & userpoints & userpoints_ref_factor + & identpoints & boundingbox & identicsurfaces & isidenticto & ideps + & filename & spline_surfaces; // TODO: & splinecurves2d & splinecurves3d + } void CSGeometry :: SaveSurfaces (ostream & out) const { diff --git a/libsrc/csg/csgeom.hpp b/libsrc/csg/csgeom.hpp index f9266de4..ee9e1260 100644 --- a/libsrc/csg/csgeom.hpp +++ b/libsrc/csg/csgeom.hpp @@ -124,6 +124,11 @@ namespace netgen UserPoint() = default; UserPoint (Point<3> p, int _index) : Point<3>(p), index(_index) { ; } int GetIndex() const { return index; } + void DoArchive(Archive& archive) + { + archive & index; + Point<3>::DoArchive(archive); + } }; private: @@ -198,6 +203,8 @@ namespace netgen void SetSplineCurve (const char * name, SplineGeometry<3> * spl); const SplineGeometry<2> * GetSplineCurve2d (const string & name) const; const SplineGeometry<3> * GetSplineCurve3d (const string & name) const; + + void DoArchive(Archive& archive); void SetFlags (const char * solidname, const Flags & flags); diff --git a/libsrc/csg/python_csg.cpp b/libsrc/csg/python_csg.cpp index b99ea2d5..05ac4acc 100644 --- a/libsrc/csg/python_csg.cpp +++ b/libsrc/csg/python_csg.cpp @@ -360,37 +360,32 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails! py::class_> (m, "CSGeometry") .def(py::init<>()) - .def("__init__", - [](CSGeometry *instance, const string & filename) - { - cout << "load geometry"; - ifstream ist(filename); - ParseCSG(ist, instance); - instance -> FindIdenticSurfaces(1e-8 * instance->MaxSize()); - }) - .def("__init__", - [](CSGeometry *instance, const py::list & solidlist) - { - cout << "csg from list"; - new (instance) CSGeometry(); - for (int i = 0; i < len(solidlist); i++) - { - py::object obj = solidlist[i]; - cout << "obj " << i << endl; - - py::extract> solid(solidlist[i]); - if(solid.check()) - { - cout << "its a solid" << endl; - solid()->AddSurfaces (*instance); - solid()->GiveUpOwner(); - int tlonr = instance->SetTopLevelObject (solid()->GetSolid()); - instance->GetTopLevelObject(tlonr) -> SetMaterial(solid()->GetMaterial()); - } - } - instance -> FindIdenticSurfaces(1e-8 * instance->MaxSize()); - }) - + .def(py::init([](const string& filename) + { + ifstream ist (filename); + auto geo = make_shared(); + ParseCSG(ist, geo.get()); + geo->FindIdenticSurfaces(1e-8 * geo->MaxSize()); + return geo; + }), py::arg("filename")) + .def(py::pickle( + [](CSGeometry& self) + { + stringstream ss; + self.Save(ss); + cout << "pickle = " << endl << ss.str() << endl; + return py::make_tuple(ss.str()); + }, + [](py::tuple state) + { + auto geo = make_shared(); + auto val = py::cast(state[0]); + cout << "unpickle = " << endl << val << endl; + stringstream ss(py::cast(state[0])); + // geo->Load(ss); + // geo->FindIdenticSurfaces(1e-8 * geo->MaxSize()); + return geo; + })) .def("Save", FunctionPointer([] (CSGeometry & self, string filename) { cout << "save geometry to file " << filename << endl; diff --git a/libsrc/csg/surface.hpp b/libsrc/csg/surface.hpp index 5e9afbdf..39a6ceee 100644 --- a/libsrc/csg/surface.hpp +++ b/libsrc/csg/surface.hpp @@ -63,6 +63,12 @@ namespace netgen //@} public: + virtual void DoArchive(Archive& archive) + { + archive & inverse & maxh & name & bcprop & bcname + & p1 & p2 & ex & ey & ez; + } + void SetName (const char * aname); const char * Name () const { return name; } @@ -234,6 +240,9 @@ namespace netgen class Primitive { + protected: + Array surfaceids; + Array surfaceactive; public: @@ -241,6 +250,10 @@ namespace netgen virtual ~Primitive(); + virtual void DoArchive(Archive& archive) + { + archive & surfaceids & surfaceactive; + } /* Check, whether box intersects solid defined by surface. @@ -299,9 +312,6 @@ namespace netgen virtual Surface & GetSurface (int i = 0) = 0; virtual const Surface & GetSurface (int i = 0) const = 0; - Array surfaceids; - Array surfaceactive; - int GetSurfaceId (int i = 0) const; void SetSurfaceId (int i, int id); int SurfaceActive (int i) const { return surfaceactive[i]; } @@ -329,6 +339,12 @@ namespace netgen OneSurfacePrimitive(); ~OneSurfacePrimitive(); + virtual void DoArchive(Archive& archive) + { + Surface::DoArchive(archive); + Primitive::DoArchive(archive); + } + virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const; virtual INSOLID_TYPE VecInSolid (const Point<3> & p, diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index 5faf7c6c..00c59ea2 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -11,7 +11,7 @@ set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) install( FILES ngexception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel ) install(FILES - archive_base.hpp array.hpp autodiff.hpp autoptr.hpp bitarray.hpp + array.hpp autodiff.hpp autoptr.hpp bitarray.hpp 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 diff --git a/libsrc/general/archive_base.hpp b/libsrc/general/archive_base.hpp deleted file mode 100644 index 9e74b0e5..00000000 --- a/libsrc/general/archive_base.hpp +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef NGS_ARCHIVE_BASE -#define NGS_ARCHIVE_BASE - -// copied from netgen - -#include -#include - -namespace ngstd -{ - - class Archive - { - bool is_output; - public: - Archive (bool ais_output) : is_output(ais_output) { ; } - virtual ~Archive() { ; } - - bool Output () { return is_output; } - bool Input () { return !is_output; } - - virtual Archive & operator & (double & d) = 0; - virtual Archive & operator & (int & i) = 0; - virtual Archive & operator & (long & i) = 0; - virtual Archive & operator & (size_t & i) = 0; - virtual Archive & operator & (short & i) = 0; - virtual Archive & operator & (unsigned char & i) = 0; - virtual Archive & operator & (bool & b) = 0; - virtual Archive & operator & (string & str) = 0; - virtual Archive & operator & (char *& str) = 0; - - template - Archive & Do (T * data, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; - - - virtual Archive & Do (double * d, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; - - virtual Archive & Do (int * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (long * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (size_t * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (short * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (unsigned char * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (bool * b, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; - - - // nvirtual Archive & Do (string * str, size_t n) - // { for (size_t j = 0; j < n; j++) { (*this) & str[j]; }; return *this; }; - // virtual Archive & operator & (char *& str) = 0; - - - // archive a pointer ... - - int cnt = 0; - std::map ptr2nr; - std::vector nr2ptr; - - /* - // necessary for msvc ??? - Archive & operator& (string* & ps) - { - return operator& (ps); - } - */ - - template - Archive & operator& (T *& p) - { - if (Output()) - { - if (!p) - { - int m2 = -2; - (*this) & m2; - return *this; - } - auto pos = ptr2nr.find( (void*) p); - if (pos == ptr2nr.end()) - { - ptr2nr[p] = cnt; - int m1 = -1; - (*this) & m1; - cnt++; - (*this) & (*p); - } - else - { - (*this) & pos->second; - } - } - else - { - int nr; - (*this) & nr; - // cout << "in, got nr " << nr << endl; - if (nr == -2) - { - p = nullptr; - } - else if (nr == -1) - { - p = new T; - // cout << "create new ptr, p = " << p << endl; - (*this) & *p; - nr2ptr.push_back(p); - } - else - { - p = (T*)nr2ptr[nr]; - // cout << "reuse ptr " << nr << ": " << p << endl; - } - } - return *this; - } - - - - - template - Archive & operator << (const T & t) - { - T ht(t); - (*this) & ht; - return *this; - } - }; - - -} - - -#endif diff --git a/libsrc/general/array.hpp b/libsrc/general/array.hpp index ead43dac..8f8263e8 100644 --- a/libsrc/general/array.hpp +++ b/libsrc/general/array.hpp @@ -400,6 +400,19 @@ namespace netgen ownmem = false; return data; } + + void DoArchive(Archive& archive) + { + if(archive.Output()) + archive << size; + else + { + size_t s; + archive & s; + SetSize(s); + } + archive.Do(data, size); + } private: @@ -778,30 +791,6 @@ namespace netgen if(in2.Contains(in1[i]) && in3.Contains(in1[i])) out.Append(in1[i]); } - - - - - template - ngstd::Archive & operator & (ngstd::Archive & archive, Array & a) - { - if (archive.Output()) - archive << a.Size(); - else - { - size_t size; - archive & size; - a.SetSize (size); - } - - /* - for (auto & ai : a) - archive & ai; - */ - archive.Do (&a[BASE], a.Size()); - return archive; - } - } #endif diff --git a/libsrc/general/hashtabl.hpp b/libsrc/general/hashtabl.hpp index 0898e58f..4d8fadc8 100644 --- a/libsrc/general/hashtabl.hpp +++ b/libsrc/general/hashtabl.hpp @@ -259,20 +259,13 @@ public: const T & GetData (const Iterator & it) const { return cont[it.BagNr()][it.Pos()]; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { ar & hash & cont; - return ar; } }; - template - inline ngstd::Archive & operator & (ngstd::Archive & archive, INDEX_2_HASHTABLE & mp) - { return mp.DoArchive(archive); } - - - template inline ostream & operator<< (ostream & ost, const INDEX_2_HASHTABLE & ht) { @@ -436,24 +429,15 @@ public: { return cont[it.BagNr()][it.Pos()]; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { ar & hash & cont; - return ar; } }; - - template - inline ngstd::Archive & operator & (ngstd::Archive & archive, INDEX_3_HASHTABLE & mp) - { return mp.DoArchive(archive); } - - - - template inline ostream & operator<< (ostream & ost, const INDEX_3_HASHTABLE & ht) { diff --git a/libsrc/general/myadt.hpp b/libsrc/general/myadt.hpp index 7c4374d8..601a3da0 100644 --- a/libsrc/general/myadt.hpp +++ b/libsrc/general/myadt.hpp @@ -17,11 +17,15 @@ #include "../include/mydefs.hpp" +#include "../core/ngcore.hpp" +namespace netgen +{ + using namespace ngcore; +} #include "ngexception.hpp" #include "parthreads.hpp" // #include "moveablemem.hpp" #include "dynamicmem.hpp" -#include "archive_base.hpp" #include "template.hpp" #include "array.hpp" diff --git a/libsrc/general/symbolta.hpp b/libsrc/general/symbolta.hpp index c246347f..b599ea42 100644 --- a/libsrc/general/symbolta.hpp +++ b/libsrc/general/symbolta.hpp @@ -69,6 +69,8 @@ public: /// 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 diff --git a/libsrc/general/table.cpp b/libsrc/general/table.cpp index 6769e03c..c964c470 100644 --- a/libsrc/general/table.cpp +++ b/libsrc/general/table.cpp @@ -213,7 +213,7 @@ namespace netgen - ngstd::Archive & BASE_TABLE :: DoArchive (ngstd::Archive & ar, int elemsize) + void BASE_TABLE :: DoArchive (Archive & ar, int elemsize) { if (ar.Output()) { @@ -248,7 +248,6 @@ namespace netgen cnt += data[i].size*elemsize; } } - return ar; } diff --git a/libsrc/general/table.hpp b/libsrc/general/table.hpp index e112e135..6a08b3dc 100644 --- a/libsrc/general/table.hpp +++ b/libsrc/general/table.hpp @@ -89,7 +89,7 @@ public: void SetElementSizesToMaxSizes (); - ngstd::Archive & DoArchive (ngstd::Archive & ar, int elemsize); + void DoArchive (Archive & ar, int elemsize); }; @@ -238,21 +238,13 @@ public: return FlatArray (data[i-BASE].size, (T*)data[i-BASE].col); } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { - return BASE_TABLE::DoArchive(ar, sizeof(T)); + BASE_TABLE::DoArchive(ar, sizeof(T)); } }; - -template - inline ngstd::Archive & operator & (ngstd::Archive & archive, TABLE & mp) - { return mp.DoArchive(archive); } - - - - template inline ostream & operator<< (ostream & ost, const TABLE & table) { diff --git a/libsrc/gprim/geomobjects.hpp b/libsrc/gprim/geomobjects.hpp index 388e9a54..ad215278 100644 --- a/libsrc/gprim/geomobjects.hpp +++ b/libsrc/gprim/geomobjects.hpp @@ -64,6 +64,12 @@ namespace netgen const T & operator() (int i) const { return x[i]; } operator const T* () const { return x; } + + void DoArchive(Archive& archive) + { + for(int i=0; i @@ -117,6 +123,12 @@ namespace netgen operator const T* () const { return x; } + void DoArchive(Archive& archive) + { + for(int i=0; i Save (ost); } - void Ngx_Mesh :: DoArchive (ngstd::Archive & archive) + void Ngx_Mesh :: DoArchive (Archive & archive) { if (archive.Input()) mesh = make_shared(); mesh->DoArchive(archive); diff --git a/libsrc/meshing/CMakeLists.txt b/libsrc/meshing/CMakeLists.txt index e9e6e211..e4eb56d9 100644 --- a/libsrc/meshing/CMakeLists.txt +++ b/libsrc/meshing/CMakeLists.txt @@ -4,6 +4,7 @@ if(NOT WIN32) $ $ $ + $ ) endif(NOT WIN32) diff --git a/libsrc/meshing/meshclass.cpp b/libsrc/meshing/meshclass.cpp index c93742fd..2291d365 100644 --- a/libsrc/meshing/meshclass.cpp +++ b/libsrc/meshing/meshclass.cpp @@ -1304,7 +1304,7 @@ namespace netgen } - void Mesh :: DoArchive (ngstd::Archive & archive) + void Mesh :: DoArchive (Archive & archive) { archive & dimension; archive & points; diff --git a/libsrc/meshing/meshclass.hpp b/libsrc/meshing/meshclass.hpp index 2de6d3ee..fe72de2a 100644 --- a/libsrc/meshing/meshclass.hpp +++ b/libsrc/meshing/meshclass.hpp @@ -517,7 +517,7 @@ namespace netgen DLL_HEADER void Merge (const string & filename, const int surfindex_offset = 0); - DLL_HEADER void DoArchive (ngstd::Archive & archive); + DLL_HEADER void DoArchive (Archive & archive); /// DLL_HEADER void ImproveMesh (const MeshingParameters & mp, OPTIMIZEGOAL goal = OPT_QUALITY); diff --git a/libsrc/meshing/meshtype.cpp b/libsrc/meshing/meshtype.cpp index cdfa7c7c..baed182e 100644 --- a/libsrc/meshing/meshtype.cpp +++ b/libsrc/meshing/meshtype.cpp @@ -148,9 +148,9 @@ namespace netgen return *this; } - ngstd::Archive & Segment :: DoArchive (ngstd::Archive & ar) + void Segment :: DoArchive (Archive & ar) { - return ar & pnums[0] & pnums[1] & pnums[2] + ar & pnums[0] & pnums[1] & pnums[2] & edgenr & singedge_left & singedge_right & si & cd2i & domin & domout & tlosurf & surfnr1 & surfnr2 @@ -2427,9 +2427,9 @@ namespace netgen bcn = &default_bcname; } - ngstd::Archive & FaceDescriptor :: DoArchive (ngstd::Archive & ar) + void FaceDescriptor :: DoArchive (Archive & ar) { - return ar & surfnr & domin & domout & tlosurf & bcprop + ar & surfnr & domin & domout & tlosurf & bcprop & surfcolour.X() & surfcolour.Y() & surfcolour.Z() & bcname & domin_singular & domout_singular ; @@ -2482,7 +2482,7 @@ namespace netgen maxidentnr = 0; } - ngstd::Archive & Identifications :: DoArchive (ngstd::Archive & ar) + void Identifications :: DoArchive (Archive & ar) { ar & maxidentnr; ar & identifiedpoints & identifiedpoints_nr; @@ -2503,7 +2503,6 @@ namespace netgen for (auto & t : type) ar & (unsigned char&)(t); } - return ar; } diff --git a/libsrc/meshing/meshtype.hpp b/libsrc/meshing/meshtype.hpp index 5fe1d8a6..e8737e93 100644 --- a/libsrc/meshing/meshtype.hpp +++ b/libsrc/meshing/meshtype.hpp @@ -171,13 +171,9 @@ namespace netgen enum { BASE = 1 }; #endif - ngstd::Archive & DoArchive (ngstd::Archive & ar) { return ar & i; } + void DoArchive (Archive & ar) { ar & i; } }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, PointIndex & mp) - { return mp.DoArchive(archive); } - - inline istream & operator>> (istream & ist, PointIndex & pi) { int i; ist >> i; pi = PointIndex(i); return ist; @@ -247,14 +243,9 @@ namespace netgen SurfaceElementIndex & operator-- () { --i; return *this; } SurfaceElementIndex & operator+= (int inc) { i+=inc; return *this; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) { return ar & i; } + void DoArchive (Archive & ar) { ar & i; } }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, SurfaceElementIndex & mp) - { return mp.DoArchive(archive); } - - - inline istream & operator>> (istream & ist, SurfaceElementIndex & pi) { int i; ist >> i; pi = i; return ist; @@ -337,19 +328,13 @@ namespace netgen static MPI_Datatype MyGetMPIType ( ); #endif - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { ar & x[0] & x[1] & x[2] & layer & singular; ar & (unsigned char&)(type); - return ar; } }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, MeshPoint & mp) - { return mp.DoArchive(archive); } - - - inline ostream & operator<<(ostream & s, const MeshPoint & pt) { return (s << Point<3> (pt)); @@ -497,7 +482,7 @@ namespace netgen /// const PointGeomInfo & GeomInfoPiMod (int i) const { return geominfo[(i-1) % np]; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { short _np, _typ; bool _curved, _vis, _deleted; @@ -511,7 +496,6 @@ namespace netgen visible = _vis; deleted = _deleted; } for (size_t i = 0; i < np; i++) ar & pnum[i]; - return ar; } void SetIndex (int si) { index = si; } @@ -630,9 +614,6 @@ namespace netgen #endif }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, Element2d & mp) - { return mp.DoArchive(archive); } - ostream & operator<<(ostream & s, const Element2d & el); @@ -774,7 +755,7 @@ namespace netgen /// const PointIndex & PNumMod (int i) const { return pnum[(i-1) % np]; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { short _np, _typ; if (ar.Output()) @@ -784,7 +765,6 @@ namespace netgen { np = _np; typ = ELEMENT_TYPE(_typ); } for (size_t i = 0; i < np; i++) ar & pnum[i]; - return ar; } /// @@ -928,9 +908,6 @@ namespace netgen int hp_elnr; }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, Element & mp) - { return mp.DoArchive(archive); } - ostream & operator<<(ostream & s, const Element & el); @@ -1049,12 +1026,9 @@ namespace netgen #else int GetPartition () const { return 0; } #endif - ngstd::Archive & DoArchive (ngstd::Archive & ar); + void DoArchive (Archive & ar); }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, Segment & mp) - { return mp.DoArchive(archive); } - ostream & operator<<(ostream & s, const Segment & seg); @@ -1142,13 +1116,9 @@ namespace netgen // friend ostream & operator<<(ostream & s, const FaceDescriptor & fd); friend class Mesh; - ngstd::Archive & DoArchive (ngstd::Archive & ar); + void DoArchive (Archive & ar); }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, FaceDescriptor & mp) - { return mp.DoArchive(archive); } - - ostream & operator<< (ostream & s, const FaceDescriptor & fd); @@ -1516,12 +1486,8 @@ namespace netgen DLL_HEADER void Print (ostream & ost) const; - ngstd::Archive & DoArchive (ngstd::Archive & ar); + void DoArchive (Archive & ar); }; - - inline ngstd::Archive & operator & (ngstd::Archive & archive, Identifications & mp) - { return mp.DoArchive(archive); } - } From 63b7719c22f71204b2d5f0f44761c2d1576f3f18 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 3 Dec 2018 11:38:11 +0100 Subject: [PATCH 05/46] Update pybind11, remove evil hack --- external_dependencies/pybind11 | 2 +- libsrc/general/ngpython.hpp | 23 ----------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/external_dependencies/pybind11 b/external_dependencies/pybind11 index 2a150736..e2b884c3 160000 --- a/external_dependencies/pybind11 +++ b/external_dependencies/pybind11 @@ -1 +1 @@ -Subproject commit 2a150736601bb3113877bb673fb934bb60d46ec5 +Subproject commit e2b884c33bcde70b2ea562ffa52dd7ebee276d50 diff --git a/libsrc/general/ngpython.hpp b/libsrc/general/ngpython.hpp index dacbb822..fa9862b1 100644 --- a/libsrc/general/ngpython.hpp +++ b/libsrc/general/ngpython.hpp @@ -1,28 +1,5 @@ #ifdef NG_PYTHON -// BEGIN EVIL HACK: Patch PyThread_get_key_value/PyThread_tss_get inside pybind11 to avoid deadlocks -// see https://github.com/pybind/pybind11/pull/1211 (please merge!) -#if defined(__GNUG__) && !defined(__clang__) -# pragma GCC diagnostic ignored "-Wattributes" -#endif -#include -#include -#include -#undef PYBIND11_TLS_GET_VALUE -#if PY_VERSION_HEX >= 0x03070000 - inline void * PYBIND11_TLS_GET_VALUE(Py_tss_t *state) { - PyThreadState *tstate = (PyThreadState *) PyThread_tss_get(state); - if (!tstate) tstate = PyGILState_GetThisThreadState(); - return tstate; - } -#else - inline void * PYBIND11_TLS_GET_VALUE(int state) { - PyThreadState *tstate = (PyThreadState *) PyThread_get_key_value(state); - if (!tstate) tstate = PyGILState_GetThisThreadState(); - return tstate; - } -#endif -// END EVIL HACK #include #include #include From 8e29d38fc1750749fa23efc9fcbeae1e09152587 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 3 Dec 2018 16:28:04 +0100 Subject: [PATCH 06/46] archive works for pointers and shared_ptrs (even with mult. inheritance and virtual base classes) --- CMakeLists.txt | 6 + cmake/SuperBuild.cmake | 1 + cmake/external_projects/catch.cmake | 18 +++ libsrc/core/CMakeLists.txt | 4 +- libsrc/core/archive.hpp | 2 + libsrc/core/basearchive.cpp | 4 +- libsrc/core/basearchive.hpp | 196 ++++++++++++++++++++++++---- libsrc/meshing/CMakeLists.txt | 3 +- tests/CMakeLists.txt | 1 + tests/catch/CMakeLists.txt | 30 +++++ tests/catch/archive.cpp | 176 +++++++++++++++++++++++++ tests/catch/main.cpp | 3 + 12 files changed, 414 insertions(+), 30 deletions(-) create mode 100644 cmake/external_projects/catch.cmake create mode 100644 tests/catch/CMakeLists.txt create mode 100644 tests/catch/archive.cpp create mode 100644 tests/catch/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f4bfd9e..3e8f78c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ option( INTEL_MIC "cross compile for intel xeon phi") option( INSTALL_PROFILES "install environment variable settings to /etc/profile.d" OFF ) option( USE_CCACHE "use ccache") option( USE_INTERNAL_TCL "Compile tcl files into the code and don't install them" ON) +option( ENABLE_UNIT_TESTS "Enable Catch unit tests") option( USE_SUPERBUILD "use ccache" ON) @@ -341,6 +342,11 @@ execute_process(COMMAND hdiutil create -volname Netgen -srcfolder ${CMAKE_INSTAL enable_testing() include(CTest) +if(ENABLE_UNIT_TESTS) + include(${CMAKE_CURRENT_LIST_DIR}/cmake/external_projects/catch.cmake) +endif(ENABLE_UNIT_TESTS) + + ####################################################################### add_subdirectory(libsrc) diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index 78be04ec..c5b3cb47 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -140,6 +140,7 @@ set_vars( NETGEN_CMAKE_ARGS INTEL_MIC CMAKE_PREFIX_PATH CMAKE_INSTALL_PREFIX + ENABLE_UNIT_TESTS ) # propagate all variables set on the command line using cmake -DFOO=BAR diff --git a/cmake/external_projects/catch.cmake b/cmake/external_projects/catch.cmake new file mode 100644 index 00000000..0f79e6c7 --- /dev/null +++ b/cmake/external_projects/catch.cmake @@ -0,0 +1,18 @@ +include (ExternalProject) +find_program(GIT_EXECUTABLE git) +ExternalProject_Add( + project_catch + PREFIX ${CMAKE_BINARY_DIR}/catch + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v2.0.1 + TIMEOUT 10 + UPDATE_COMMAND "" # ${GIT_EXECUTABLE} pull + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) + +# Expose required variable (CATCH_INCLUDE_DIR) to parent scope +ExternalProject_Get_Property(project_catch source_dir) +set(CATCH_INCLUDE_DIR ${source_dir}/single_include CACHE INTERNAL "Path to include folder for Catch") diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index d49da46b..8b14b211 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,8 +1,10 @@ add_definitions(-DNGINTERFACE_EXPORTS) -add_library(ngcore OBJECT basearchive.cpp) +add_library(ngcore basearchive.cpp) set_target_properties(ngcore PROPERTIES POSITION_INDEPENDENT_CODE ON ) +install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) + install(FILES ngcore.hpp archive.hpp basearchive.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel ) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 639102f4..7b213b8d 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -16,6 +16,7 @@ namespace ngcore : BinaryOutArchive(std::make_shared(filename)) {} virtual ~BinaryOutArchive () { FlushBuffer(); } + using Archive::operator&; virtual Archive & operator & (double & d) { return Write(d); } virtual Archive & operator & (int & i) @@ -81,6 +82,7 @@ namespace ngcore BinaryInArchive (std::string filename) : BinaryInArchive(std::make_shared(filename)) {} + using Archive::operator&; virtual Archive & operator & (double & d) { Read(d); return *this; } virtual Archive & operator & (int & i) diff --git a/libsrc/core/basearchive.cpp b/libsrc/core/basearchive.cpp index 1fcbe8b8..434fbab5 100644 --- a/libsrc/core/basearchive.cpp +++ b/libsrc/core/basearchive.cpp @@ -3,9 +3,9 @@ namespace ngcore { - std::map>& GetArchiveRegister() + std::map& GetArchiveRegister() { - static std::map> type_register = {}; + static std::map type_register; return type_register; } } diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index a43c4bc0..a97cd28c 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -20,7 +20,31 @@ namespace ngcore static constexpr bool value = type::value; }; - std::map>& GetArchiveRegister(); + // Info stored by registering a class using the RegisterClassForArchive struct in the map + // stored in GetArchiveRegister + struct ClassArchiveInfo + { + // create new object of this type and return a void* pointer that is points to the location + // of the (base)class given by type_info + std::function creator; + // This caster takes a void* pointer to the type stored in this info and casts it to a + // void* pointer pointing to the (base)class type_info + std::function upcaster; + // This caster takes a void* pointer to the (base)class type_info and returns void* pointing + // to the type stored in this info + std::function downcaster; + }; + + // Returns a map of from the mangled typeids to the ClassArchiveInfo + std::map& GetArchiveRegister(); + + // Helper class for up-/downcasting + template + struct Caster + { + static void* tryUpcast(const std::type_info& ti, T* p); + static void* tryDowncast(const std::type_info& ti, void* p); + }; // Base Archive class class Archive @@ -76,11 +100,12 @@ namespace ngcore size = v.size(); (*this) & size; if(!is_output) - v.reserve(size); + v.resize(size); Do(&v[0], size); return (*this); } // Archive arrays ===================================================== + // this functions can be overloaded in Archive implementations for more efficiency template Archive & Do (T * data, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; @@ -122,32 +147,87 @@ namespace ngcore // save -2 for nullptr if(!ptr) return (*this) << -2; - auto pos = shared_ptr2nr.find((void*) ptr.get()); + + void* reg_ptr = ptr.get(); + bool neededDowncast = false; + if constexpr(has_DoArchive::value) + { + if(GetArchiveRegister().count(std::string(typeid(*ptr).name())) == 0) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + + typeid(*ptr).name() + + " not registered for archive"); + else + reg_ptr = GetArchiveRegister()[typeid(*ptr).name()].downcaster(typeid(T), ptr.get()); + if(reg_ptr != (void*) ptr.get()) + neededDowncast = true; + } + auto pos = shared_ptr2nr.find(reg_ptr); // if not found store -1 and the pointer if(pos == shared_ptr2nr.end()) { - shared_ptr2nr[(void*) ptr.get()] = shared_ptr_count++; auto p = ptr.get(); - return (*this) << -1 & p; + (*this) << -1; + (*this) & neededDowncast & p; + if(neededDowncast) + (*this) << std::string(typeid(*ptr).name()); + shared_ptr2nr[reg_ptr] = shared_ptr_count++; + return *this; } - // if found store the position - return (*this) << pos->second; + // if found store the position and if it has to be downcasted and how + (*this) << pos->second << neededDowncast; + if(neededDowncast) + (*this) << std::string(typeid(*ptr).name()); + return (*this); } else // Input { int nr; (*this) & nr; if(nr == -2) - ptr = nullptr; + { + ptr = nullptr; + return *this; + } else if (nr == -1) { T* p; - (*this) & p; + bool neededDowncast; + (*this) & neededDowncast & p; ptr = std::shared_ptr(p); - nr2shared_ptr.push_back(ptr); + if(neededDowncast) + { + std::string name; + (*this) & name; + auto info = GetArchiveRegister()[name]; + nr2shared_ptr.push_back(std::shared_ptr(std::static_pointer_cast(ptr), + info.downcaster(typeid(T), + ptr.get()))); + } + else + nr2shared_ptr.push_back(ptr); } else - ptr = std::reinterpret_pointer_cast(nr2shared_ptr[nr]); + { + auto other = nr2shared_ptr[nr]; + bool neededDowncast; + (*this) & neededDowncast; + if(neededDowncast) + { + if constexpr(has_DoArchive::value) + { + std::string name; + (*this) & name; + auto info = GetArchiveRegister()[name]; + ptr = std::static_pointer_cast(std::shared_ptr(other, + info.upcaster(typeid(T), + other.get()))); + } + else + throw std::runtime_error("Shouldn't get here..."); + } + else + ptr = std::static_pointer_cast(other); + } } return *this; } @@ -165,11 +245,21 @@ namespace ngcore (*this) & m2; return *this; } - auto pos = ptr2nr.find( (void*) p); + void* reg_ptr = (void*)p; + if constexpr(has_DoArchive::value) + { + if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) + throw std::runtime_error(std::string("Archive error: Polimorphic type ") + + typeid(*p).name() + + " not registered for archive"); + else + reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), p); + } + auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry if (pos == ptr2nr.end()) { - ptr2nr[(void*) p] = ptr_count++; + ptr2nr[reg_ptr] = ptr_count++; if(typeid(*p) == typeid(T)) if constexpr (std::is_constructible::value) { @@ -183,7 +273,7 @@ namespace ngcore // We want this special behaviour only for our classes that implement DoArchive if constexpr(has_DoArchive::value) { - if(GetArchiveRegister().count(typeid(*p).name()) == 0) + if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) throw std::runtime_error(std::string("Archive error: Polimorphic type ") + typeid(*p).name() + " not registered for archive"); @@ -199,13 +289,13 @@ namespace ngcore else { (*this) & pos->second; + (*this) << std::string(typeid(*p).name()); } } else { int nr; (*this) & nr; - // cout << "in, got nr " << nr << endl; if (nr == -2) { p = nullptr; @@ -215,9 +305,8 @@ namespace ngcore if constexpr (std::is_constructible::value) { p = new T; - // cout << "create new ptr, p = " << p << endl; - (*this) & *p; nr2ptr.push_back(p); + (*this) & *p; } else throw std::runtime_error("Class isn't registered properly"); @@ -230,16 +319,25 @@ namespace ngcore { std::string name; (*this) & name; - p = reinterpret_cast(GetArchiveRegister()[name]()); - nr2ptr.push_back(p); + auto info = GetArchiveRegister()[name]; + p = (T*) info.creator(typeid(T)); + nr2ptr.push_back(info.downcaster(typeid(T),p)); + (*this) & *p; } else throw std::runtime_error("Class isn't registered properly"); } else { - p = (T*)nr2ptr[nr]; - // cout << "reuse ptr " << nr << ": " << p << endl; + std::string name; + (*this) & name; + if constexpr(has_DoArchive::value) + { + auto info = GetArchiveRegister()[name]; + p = (T*) info.upcaster(typeid(T), nr2ptr[nr]); + } + else + p = (T*) nr2ptr[nr]; } } return *this; @@ -253,14 +351,62 @@ namespace ngcore (*this) & ht; return *this; } + + virtual void FlushBuffer() {} + }; + + template + class RegisterClassForArchive + { + public: + RegisterClassForArchive() + { + static_assert(std::is_constructible_v, "Class registered for archive must be default constructible"); + ClassArchiveInfo info; + info.creator = [this,&info](const std::type_info& ti) -> void* + { return typeid(T) == ti ? new T : Caster::tryUpcast(ti, new T); }; + info.upcaster = [this](const std::type_info& ti, void* p) -> void* + { return typeid(T) == ti ? p : Caster::tryUpcast(ti, (T*) p); }; + info.downcaster = [this](const std::type_info& ti, void* p) -> void* + { return typeid(T) == ti ? p : Caster::tryDowncast(ti, p); }; + GetArchiveRegister()[std::string(typeid(T).name())] = info; + } }; template - void RegisterClassForArchive() + struct Caster { - static_assert(std::is_constructible_v, "Class registered for archive must be default constructible"); - GetArchiveRegister()[std::string(typeid(T).name())] = []() -> void* { return new T; }; - } + static void* tryUpcast (const std::type_info& ti, T* p) + { + throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!"); + } + static void* tryDowncast (const std::type_info& ti, void* p) + { + throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!"); + } + }; + + template + struct Caster + { + static void* tryUpcast(const std::type_info& ti, T* p) + { + try + { return GetArchiveRegister()[typeid(B1).name()].upcaster(ti, (void*) (dynamic_cast(p))); } + catch(std::exception) + { return Caster::tryUpcast(ti, p); } + } + + static void* tryDowncast(const std::type_info& ti, void* p) + { + if(typeid(B1) == ti) + return dynamic_cast((B1*) p); + try + { return GetArchiveRegister()[typeid(B1).name()].downcaster(ti, (void*) ((B1*)p)); } + catch(std::exception) + { return Caster::tryDowncast(ti, p); } + } + }; } #endif // NG_BASEARCHIVE_HPP diff --git a/libsrc/meshing/CMakeLists.txt b/libsrc/meshing/CMakeLists.txt index e4eb56d9..bc9f7f18 100644 --- a/libsrc/meshing/CMakeLists.txt +++ b/libsrc/meshing/CMakeLists.txt @@ -4,7 +4,6 @@ if(NOT WIN32) $ $ $ - $ ) endif(NOT WIN32) @@ -31,7 +30,7 @@ if(APPLE) endif(APPLE) if(NOT WIN32) - target_link_libraries( mesh ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) + target_link_libraries( mesh ngcore ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) install( TARGETS mesh ${NG_INSTALL_DIR}) endif(NOT WIN32) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f898217f..a0783363 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1 +1,2 @@ +add_subdirectory(catch) add_subdirectory(pytest) diff --git a/tests/catch/CMakeLists.txt b/tests/catch/CMakeLists.txt new file mode 100644 index 00000000..d980d7f8 --- /dev/null +++ b/tests/catch/CMakeLists.txt @@ -0,0 +1,30 @@ + +if(ENABLE_UNIT_TESTS) +add_custom_target(unit_tests) + +# Build catch_main test object +message("netgen include dir = ${NETGEN_INCLUDE_DIR_ABSOLUTE} --------------------------------------") +include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include}) +add_library(catch_main STATIC main.cpp) +set_target_properties(catch_main PROPERTIES CXX_STANDARD 17) +add_dependencies(unit_tests catch_main) +add_dependencies(catch_main project_catch) + +# ensure the test targets are built before testing +add_test(NAME unit_tests_built COMMAND ${CMAKE_COMMAND} --build . --target unit_tests --config ${CMAKE_BUILD_TYPE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../.. ) + +macro(add_unit_test name sources) + add_executable(test_${name} ${sources} ) + if (WIN32) + target_link_libraries(test_${name} ngcore catch_main) + else(WIN32) + target_link_libraries(test_${name} ngcore catch_main) + endif(WIN32) + + add_dependencies(unit_tests test_${name}) + add_test(NAME unit_${name} COMMAND test_${name}) + set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built) +endmacro() + +add_unit_test(archive archive.cpp) +endif(ENABLE_UNIT_TESTS) diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp new file mode 100644 index 00000000..d34e3878 --- /dev/null +++ b/tests/catch/archive.cpp @@ -0,0 +1,176 @@ + +#include "catch.hpp" +#include <../core/ngcore.hpp> +using namespace ngcore; +using namespace std; + +class CommonBase +{ + public: + virtual ~CommonBase() {} + + virtual void DoArchive(Archive& archive) { } +}; + +class SharedPtrHolder : virtual public CommonBase +{ +public: + vector> names; + virtual ~SharedPtrHolder() + { } + + virtual void DoArchive(Archive& archive) { archive & names; } +}; + +class PtrHolder : virtual public CommonBase +{ +public: + vector numbers; + virtual ~PtrHolder() {} + + virtual void DoArchive(Archive& archive) { archive & numbers; } +}; + +class SharedPtrAndPtrHolder : public SharedPtrHolder, public PtrHolder +{ +public: + virtual ~SharedPtrAndPtrHolder() {} + virtual void DoArchive(Archive& archive) + { + SharedPtrHolder::DoArchive(archive); + PtrHolder::DoArchive(archive); + } +}; + +class NotRegisteredForArchive : public SharedPtrAndPtrHolder {}; + +class OneMoreDerivedClass : public SharedPtrAndPtrHolder {}; + +static RegisterClassForArchive regb; +static RegisterClassForArchive regsp; +static RegisterClassForArchive regp; +static RegisterClassForArchive regspp; +static RegisterClassForArchive regom; + +void testSharedPointer(Archive& in, Archive& out) +{ + SECTION("Same shared ptr") + { + static_assert(has_DoArchive::value, ""); + SharedPtrHolder holder, holder2; + holder.names.push_back(make_shared("name")); + holder2.names = holder.names; // same shared ptr + out & holder & holder2; + out.FlushBuffer(); + SharedPtrHolder inholder, inholder2; + in & inholder & inholder2; + CHECK(inholder.names.size() == 1); + CHECK(inholder.names[0] == inholder2.names[0]); + CHECK(inholder.names[0].use_count() == 3); // one shared ptr is still kept in the archive + CHECK(*inholder.names[0] == "name"); + } +} + +void testPointer(Archive& in, Archive& out) +{ + SECTION("Same pointer") + { + PtrHolder holder, holder2; + holder.numbers.push_back(new int(3)); + holder2.numbers = holder.numbers; // same shared ptr + out & holder & holder2; + out.FlushBuffer(); + PtrHolder inholder, inholder2; + in & inholder & inholder2; + CHECK(inholder.numbers.size() == 1); + CHECK(inholder.numbers[0] == inholder2.numbers[0]); + CHECK(*inholder.numbers[0] == 3); + } +} + +void testMultipleInheritance(Archive& in, Archive& out) +{ + PtrHolder* p = new OneMoreDerivedClass; + p->numbers.push_back(new int(2)); + auto p2 = dynamic_cast(p); + p2->names.push_back(make_shared("test")); + auto sp1 = shared_ptr(p); + auto sp2 = dynamic_pointer_cast(sp1); + auto checkPtr = [] (auto pin, auto pin2) + { + CHECK(typeid(*pin) == typeid(*pin2)); + CHECK(typeid(*pin) == typeid(OneMoreDerivedClass)); + CHECK(*pin2->names[0] == "test"); + CHECK(*pin->numbers[0] == 2); + CHECK(dynamic_cast(pin) == dynamic_cast(pin2)); + REQUIRE(dynamic_cast(pin2) != nullptr); + CHECK(*dynamic_cast(pin2)->numbers[0] == 2); + CHECK(*pin->numbers[0] == *dynamic_cast(pin2)->numbers[0]); + REQUIRE(dynamic_cast(pin) != nullptr); + CHECK(dynamic_cast(pin)->names[0] == pin2->names[0]); + }; + SECTION("Archive ptrs to leaves of mult. inh.") + { + out & p & p2; + out.FlushBuffer(); + PtrHolder* pin; + SharedPtrHolder* pin2; + in & pin & pin2; + checkPtr(pin, pin2); + } + SECTION("Archive shared ptrs to leaves of mult. inh.") + { + out & sp1 & sp2; + out.FlushBuffer(); + shared_ptr pin; + shared_ptr pin2; + in & pin & pin2; + checkPtr(pin.get(), pin2.get()); + } + SECTION("Virtual base class") + { + CommonBase* b = dynamic_cast(p); + out & b & p; + PtrHolder* pin; + CommonBase* bin; + in & bin & pin; + checkPtr(pin, dynamic_cast(bin)); + } +} + +void testArchive(Archive& in, Archive& out) +{ + SECTION("SharedPtr") + { + testSharedPointer(in, out); + } + SECTION("Pointer") + { + testPointer(in, out); + } + SECTION("Multiple inheritance") + { + testMultipleInheritance(in, out); + } + SECTION("Not registered") + { + SharedPtrAndPtrHolder* p = new NotRegisteredForArchive; + REQUIRE_THROWS(out & p, Catch::Contains("not registered for archive")); + } +} + +TEST_CASE("BinaryArchive") +{ + auto stream = make_shared(); + BinaryOutArchive out(stream); + BinaryInArchive in(stream); + testArchive(in, out); +} + +TEST_CASE("TextArchive") +{ + auto stream = make_shared(); + TextOutArchive out(stream); + TextInArchive in(stream); + testArchive(in, out); +} diff --git a/tests/catch/main.cpp b/tests/catch/main.cpp new file mode 100644 index 00000000..de419564 --- /dev/null +++ b/tests/catch/main.cpp @@ -0,0 +1,3 @@ + +#define CATCH_CONFIG_MAIN +#include From b2a2c648454caa69eb6f6d128754da325f6d3d3b Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 3 Dec 2018 17:18:12 +0100 Subject: [PATCH 07/46] fix for classes that have DoArchive but no inheritance. Some comments --- libsrc/core/basearchive.hpp | 105 ++++++++++++++++++++++-------------- tests/catch/archive.cpp | 74 +++++++++++++++++++++++-- 2 files changed, 135 insertions(+), 44 deletions(-) diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index a97cd28c..79e4eaf9 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -150,17 +150,21 @@ namespace ngcore void* reg_ptr = ptr.get(); bool neededDowncast = false; - if constexpr(has_DoArchive::value) - { - if(GetArchiveRegister().count(std::string(typeid(*ptr).name())) == 0) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + typeid(*ptr).name() - + " not registered for archive"); - else - reg_ptr = GetArchiveRegister()[typeid(*ptr).name()].downcaster(typeid(T), ptr.get()); - if(reg_ptr != (void*) ptr.get()) - neededDowncast = true; - } + // Downcasting is only possible for our registered classes + if(typeid(T) != typeid(*ptr)) + { + if constexpr(has_DoArchive::value) + { + if(GetArchiveRegister().count(std::string(typeid(*ptr).name())) == 0) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + + typeid(*ptr).name() + + " not registered for archive"); + reg_ptr = GetArchiveRegister()[typeid(*ptr).name()].downcaster(typeid(T), ptr.get()); + // if there was a true downcast we have to store more information + if(reg_ptr != (void*) ptr.get()) + neededDowncast = true; + } + } auto pos = shared_ptr2nr.find(reg_ptr); // if not found store -1 and the pointer if(pos == shared_ptr2nr.end()) @@ -168,6 +172,7 @@ namespace ngcore auto p = ptr.get(); (*this) << -1; (*this) & neededDowncast & p; + // if we did downcast we store the true type as well if(neededDowncast) (*this) << std::string(typeid(*ptr).name()); shared_ptr2nr[reg_ptr] = shared_ptr_count++; @@ -183,22 +188,27 @@ namespace ngcore { int nr; (*this) & nr; + // -2 restores a nullptr if(nr == -2) { ptr = nullptr; return *this; } + // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it else if (nr == -1) { T* p; bool neededDowncast; (*this) & neededDowncast & p; ptr = std::shared_ptr(p); + // if we did downcast we need to store a shared_ptr to the true object if(neededDowncast) { std::string name; (*this) & name; auto info = GetArchiveRegister()[name]; + // for this we use an aliasing constructor to create a shared pointer sharing lifetime + // with our shared ptr, but pointing to the true object nr2shared_ptr.push_back(std::shared_ptr(std::static_pointer_cast(ptr), info.downcaster(typeid(T), ptr.get()))); @@ -213,11 +223,15 @@ namespace ngcore (*this) & neededDowncast; if(neededDowncast) { + // if there was a downcast we can expect the class to be registered (since archiving + // wouldn't have worked else) if constexpr(has_DoArchive::value) { std::string name; (*this) & name; auto info = GetArchiveRegister()[name]; + // same trick as above, create a shared ptr sharing lifetime with + // the shared_ptr in the register, but pointing to our object ptr = std::static_pointer_cast(std::shared_ptr(other, info.upcaster(typeid(T), other.get()))); @@ -240,21 +254,20 @@ namespace ngcore { // if the pointer is null store -2 if (!p) - { - int m2 = -2; - (*this) & m2; - return *this; - } + return (*this) << -2; void* reg_ptr = (void*)p; - if constexpr(has_DoArchive::value) - { - if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) - throw std::runtime_error(std::string("Archive error: Polimorphic type ") - + typeid(*p).name() - + " not registered for archive"); - else - reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), p); - } + if(typeid(T) != typeid(*p)) + { + if constexpr(has_DoArchive::value) + { + if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + + typeid(*p).name() + + " not registered for archive"); + else + reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), p); + } + } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry if (pos == ptr2nr.end()) @@ -270,11 +283,14 @@ namespace ngcore typeid(*p).name() + " does not provide a default constructor!"); else { - // We want this special behaviour only for our classes that implement DoArchive + // if a pointer to a base class is archived, the class hierarchy must be registered + // to avoid compile time issues we allow this behaviour only for "our" classes that + // implement a void DoArchive(Archive&) member function + // To recreate the object we need to store the true type of it if constexpr(has_DoArchive::value) { if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) - throw std::runtime_error(std::string("Archive error: Polimorphic type ") + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + typeid(*p).name() + " not registered for archive"); else @@ -289,18 +305,18 @@ namespace ngcore else { (*this) & pos->second; - (*this) << std::string(typeid(*p).name()); + bool downcasted = !(reg_ptr == (void*) p); + // store if the class has been downcasted and the name + (*this) << downcasted << std::string(typeid(*p).name()); } } else { int nr; (*this) & nr; - if (nr == -2) - { + if (nr == -2) // restore a nullptr p = nullptr; - } - else if (nr == -1) + else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) { if constexpr (std::is_constructible::value) { @@ -312,15 +328,19 @@ namespace ngcore throw std::runtime_error("Class isn't registered properly"); } - else if(nr == -3) + else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... { - // We want this special behaviour only for our classes that implement DoArchive + // As stated above, we want this special behaviour only for our classes that implement DoArchive if constexpr(has_DoArchive::value) { std::string name; (*this) & name; auto info = GetArchiveRegister()[name]; + // the creator creates a new object of type name, and returns a void* pointing + // to T (which may have an offset) p = (T*) info.creator(typeid(T)); + // we store the downcasted pointer (to be able to find it again from + // another class in a multiple inheritance tree) nr2ptr.push_back(info.downcaster(typeid(T),p)); (*this) & *p; } @@ -329,13 +349,18 @@ namespace ngcore } else { + bool downcasted; std::string name; - (*this) & name; - if constexpr(has_DoArchive::value) - { - auto info = GetArchiveRegister()[name]; - p = (T*) info.upcaster(typeid(T), nr2ptr[nr]); - } + (*this) & downcasted & name; + if(downcasted) + { + // if the class has been downcasted we can assume it is in the register + if constexpr(has_DoArchive::value) + { + auto info = GetArchiveRegister()[name]; + p = (T*) info.upcaster(typeid(T), nr2ptr[nr]); + } + } else p = (T*) nr2ptr[nr]; } diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index d34e3878..dc31be16 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -6,10 +6,11 @@ using namespace std; class CommonBase { - public: +public: + int a; virtual ~CommonBase() {} - virtual void DoArchive(Archive& archive) { } + virtual void DoArchive(Archive& archive) { archive & a; } }; class SharedPtrHolder : virtual public CommonBase @@ -19,7 +20,11 @@ public: virtual ~SharedPtrHolder() { } - virtual void DoArchive(Archive& archive) { archive & names; } + virtual void DoArchive(Archive& archive) + { + CommonBase::DoArchive(archive); + archive & names; + } }; class PtrHolder : virtual public CommonBase @@ -28,7 +33,11 @@ public: vector numbers; virtual ~PtrHolder() {} - virtual void DoArchive(Archive& archive) { archive & numbers; } + virtual void DoArchive(Archive& archive) + { + CommonBase::DoArchive(archive); + archive & numbers; + } }; class SharedPtrAndPtrHolder : public SharedPtrHolder, public PtrHolder @@ -42,6 +51,18 @@ public: } }; +// Classes without virt. or multiple inheritance do not need to be registered +class SimpleClass : public CommonBase +{ +public: + double d; + virtual void DoArchive(Archive& ar) + { + CommonBase::DoArchive(ar); + ar & d; + } +}; + class NotRegisteredForArchive : public SharedPtrAndPtrHolder {}; class OneMoreDerivedClass : public SharedPtrAndPtrHolder {}; @@ -52,6 +73,19 @@ static RegisterClassForArchive regp; static RegisterClassForArchive regspp; static RegisterClassForArchive regom; +void testNullPtr(Archive& in, Archive& out) +{ + SharedPtrHolder* p = nullptr; + shared_ptr sp = nullptr; + out & p & sp; + out.FlushBuffer(); + SharedPtrHolder* pin; + shared_ptr spin; + in & pin & spin; + CHECK(pin == nullptr); + CHECK(spin == nullptr); +} + void testSharedPointer(Archive& in, Archive& out) { SECTION("Same shared ptr") @@ -92,6 +126,7 @@ void testMultipleInheritance(Archive& in, Archive& out) { PtrHolder* p = new OneMoreDerivedClass; p->numbers.push_back(new int(2)); + p->a = 5; auto p2 = dynamic_cast(p); p2->names.push_back(make_shared("test")); auto sp1 = shared_ptr(p); @@ -103,6 +138,8 @@ void testMultipleInheritance(Archive& in, Archive& out) CHECK(*pin2->names[0] == "test"); CHECK(*pin->numbers[0] == 2); CHECK(dynamic_cast(pin) == dynamic_cast(pin2)); + CHECK(pin->a == pin2->a); + CHECK(pin->a == 5); REQUIRE(dynamic_cast(pin2) != nullptr); CHECK(*dynamic_cast(pin2)->numbers[0] == 2); CHECK(*pin->numbers[0] == *dynamic_cast(pin2)->numbers[0]); @@ -136,6 +173,31 @@ void testMultipleInheritance(Archive& in, Archive& out) in & bin & pin; checkPtr(pin, dynamic_cast(bin)); } + SECTION("Simple class without register") + { + auto a = new SimpleClass; + a->a = 5; + a->d = 2.3; + SECTION("check pointer") + { + out & a; + out.FlushBuffer(); + SimpleClass* ain; + in & ain; + CHECK(ain->a == 5); + CHECK(ain->d == 2.3); + } + SECTION("check shared pointer") + { + auto spa = shared_ptr(a); + out & spa; + out.FlushBuffer(); + shared_ptr spain; + in & spain; + CHECK(spain->a == 5); + CHECK(spain->d == 2.3); + } + } } void testArchive(Archive& in, Archive& out) @@ -157,6 +219,10 @@ void testArchive(Archive& in, Archive& out) SharedPtrAndPtrHolder* p = new NotRegisteredForArchive; REQUIRE_THROWS(out & p, Catch::Contains("not registered for archive")); } + SECTION("nullptr") + { + testNullPtr(in, out); + } } TEST_CASE("BinaryArchive") From 2ec3bb0df1b940564c2bb51605d8f0118b57e6a2 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 3 Dec 2018 18:07:52 +0100 Subject: [PATCH 08/46] C++ 14 for Archiver --- CMakeLists.txt | 2 +- libsrc/core/basearchive.hpp | 114 ++++++++++++++---------------------- 2 files changed, 45 insertions(+), 71 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e8f78c6..c947e762 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,7 +205,7 @@ macro(get_dll_from_lib dll_path lib_path) get_filename_component(lib_name ${lib} name) endmacro() -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 14) if(WIN32) get_WIN32_WINNT(ver) add_definitions(-D_WIN32_WINNT=${ver} -DWNT -DWNT_WINDOW -DNOMINMAX) diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index 79e4eaf9..cdd992fc 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -153,17 +153,14 @@ namespace ngcore // Downcasting is only possible for our registered classes if(typeid(T) != typeid(*ptr)) { - if constexpr(has_DoArchive::value) - { - if(GetArchiveRegister().count(std::string(typeid(*ptr).name())) == 0) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + typeid(*ptr).name() - + " not registered for archive"); - reg_ptr = GetArchiveRegister()[typeid(*ptr).name()].downcaster(typeid(T), ptr.get()); - // if there was a true downcast we have to store more information - if(reg_ptr != (void*) ptr.get()) - neededDowncast = true; - } + if(GetArchiveRegister().count(std::string(typeid(*ptr).name())) == 0) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + + typeid(*ptr).name() + + " not registered for archive"); + reg_ptr = GetArchiveRegister()[typeid(*ptr).name()].downcaster(typeid(T), ptr.get()); + // if there was a true downcast we have to store more information + if(reg_ptr != (void*) ptr.get()) + neededDowncast = true; } auto pos = shared_ptr2nr.find(reg_ptr); // if not found store -1 and the pointer @@ -225,19 +222,14 @@ namespace ngcore { // if there was a downcast we can expect the class to be registered (since archiving // wouldn't have worked else) - if constexpr(has_DoArchive::value) - { - std::string name; - (*this) & name; - auto info = GetArchiveRegister()[name]; - // same trick as above, create a shared ptr sharing lifetime with - // the shared_ptr in the register, but pointing to our object - ptr = std::static_pointer_cast(std::shared_ptr(other, - info.upcaster(typeid(T), - other.get()))); - } - else - throw std::runtime_error("Shouldn't get here..."); + std::string name; + (*this) & name; + auto info = GetArchiveRegister()[name]; + // same trick as above, create a shared ptr sharing lifetime with + // the shared_ptr in the register, but pointing to our object + ptr = std::static_pointer_cast(std::shared_ptr(other, + info.upcaster(typeid(T), + other.get()))); } else ptr = std::static_pointer_cast(other); @@ -258,15 +250,12 @@ namespace ngcore void* reg_ptr = (void*)p; if(typeid(T) != typeid(*p)) { - if constexpr(has_DoArchive::value) - { - if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + typeid(*p).name() - + " not registered for archive"); - else - reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), p); - } + if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + + typeid(*p).name() + + " not registered for archive"); + else + reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), p); } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry @@ -274,7 +263,7 @@ namespace ngcore { ptr2nr[reg_ptr] = ptr_count++; if(typeid(*p) == typeid(T)) - if constexpr (std::is_constructible::value) + if (std::is_constructible::value) { return (*this) << -1 & (*p); } @@ -287,19 +276,12 @@ namespace ngcore // to avoid compile time issues we allow this behaviour only for "our" classes that // implement a void DoArchive(Archive&) member function // To recreate the object we need to store the true type of it - if constexpr(has_DoArchive::value) - { - if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + typeid(*p).name() - + " not registered for archive"); - else - return (*this) << -3 << std::string(typeid(*p).name()) & (*p); - } - else - throw std::runtime_error(std::string("Archive error: Class ") + if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + typeid(*p).name() - + " is polymorphic but not registered for archiving"); + + " not registered for archive"); + else + return (*this) << -3 << std::string(typeid(*p).name()) & (*p); } } else @@ -318,7 +300,7 @@ namespace ngcore p = nullptr; else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) { - if constexpr (std::is_constructible::value) + if (std::is_constructible::value) { p = new T; nr2ptr.push_back(p); @@ -330,22 +312,17 @@ namespace ngcore } else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... { - // As stated above, we want this special behaviour only for our classes that implement DoArchive - if constexpr(has_DoArchive::value) - { - std::string name; - (*this) & name; - auto info = GetArchiveRegister()[name]; - // the creator creates a new object of type name, and returns a void* pointing - // to T (which may have an offset) - p = (T*) info.creator(typeid(T)); - // we store the downcasted pointer (to be able to find it again from - // another class in a multiple inheritance tree) - nr2ptr.push_back(info.downcaster(typeid(T),p)); - (*this) & *p; - } - else - throw std::runtime_error("Class isn't registered properly"); + // As stated above, we want this special behaviour only for our classes that implement DoArchive + std::string name; + (*this) & name; + auto info = GetArchiveRegister()[name]; + // the creator creates a new object of type name, and returns a void* pointing + // to T (which may have an offset) + p = (T*) info.creator(typeid(T)); + // we store the downcasted pointer (to be able to find it again from + // another class in a multiple inheritance tree) + nr2ptr.push_back(info.downcaster(typeid(T),p)); + (*this) & *p; } else { @@ -354,12 +331,9 @@ namespace ngcore (*this) & downcasted & name; if(downcasted) { - // if the class has been downcasted we can assume it is in the register - if constexpr(has_DoArchive::value) - { - auto info = GetArchiveRegister()[name]; - p = (T*) info.upcaster(typeid(T), nr2ptr[nr]); - } + // if the class has been downcasted we can assume it is in the register + auto info = GetArchiveRegister()[name]; + p = (T*) info.upcaster(typeid(T), nr2ptr[nr]); } else p = (T*) nr2ptr[nr]; @@ -386,7 +360,7 @@ namespace ngcore public: RegisterClassForArchive() { - static_assert(std::is_constructible_v, "Class registered for archive must be default constructible"); + static_assert(std::is_constructible::value, "Class registered for archive must be default constructible"); ClassArchiveInfo info; info.creator = [this,&info](const std::type_info& ti) -> void* { return typeid(T) == ti ? new T : Caster::tryUpcast(ti, new T); }; From e845a203e9a01694c398442be02f9508d77d71ca Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 3 Dec 2018 19:07:15 +0100 Subject: [PATCH 09/46] archive for pointer to abstract base classes --- libsrc/core/basearchive.hpp | 51 ++++++++++++++++++++----------------- libsrc/csg/csgeom.cpp | 4 +-- libsrc/csg/csgeom.hpp | 5 ++++ libsrc/csg/solid.hpp | 12 +++++++++ tests/catch/archive.cpp | 7 +++-- 5 files changed, 52 insertions(+), 27 deletions(-) diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index cdd992fc..f16ef942 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -5,6 +5,17 @@ namespace ngcore { class Archive; + // create new pointer of type T if it is default constructible, else throw + template + T* constructIfPossible_impl(...) + { throw std::runtime_error(std::string(typeid(T).name()) + " is not default constructible!"); } + + template::value>::type> + T* constructIfPossible_impl(int) { return new T; } + + template + T* constructIfPossible() { return constructIfPossible_impl(int{}); } + // Type trait to check if a class implements a 'void DoArchive(Archive&)' function template struct has_DoArchive @@ -255,7 +266,7 @@ namespace ngcore + typeid(*p).name() + " not registered for archive"); else - reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), p); + reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), (void*) p); } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry @@ -300,29 +311,23 @@ namespace ngcore p = nullptr; else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) { - if (std::is_constructible::value) - { - p = new T; - nr2ptr.push_back(p); - (*this) & *p; - } - else - throw std::runtime_error("Class isn't registered properly"); - + p = constructIfPossible(); + nr2ptr.push_back(p); + (*this) & *p; } else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... { - // As stated above, we want this special behaviour only for our classes that implement DoArchive - std::string name; - (*this) & name; - auto info = GetArchiveRegister()[name]; - // the creator creates a new object of type name, and returns a void* pointing - // to T (which may have an offset) - p = (T*) info.creator(typeid(T)); - // we store the downcasted pointer (to be able to find it again from - // another class in a multiple inheritance tree) - nr2ptr.push_back(info.downcaster(typeid(T),p)); - (*this) & *p; + // As stated above, we want this special behaviour only for our classes that implement DoArchive + std::string name; + (*this) & name; + auto info = GetArchiveRegister()[name]; + // the creator creates a new object of type name, and returns a void* pointing + // to T (which may have an offset) + p = (T*) info.creator(typeid(T)); + // we store the downcasted pointer (to be able to find it again from + // another class in a multiple inheritance tree) + nr2ptr.push_back(info.downcaster(typeid(T),p)); + (*this) & *p; } else { @@ -360,10 +365,10 @@ namespace ngcore public: RegisterClassForArchive() { - static_assert(std::is_constructible::value, "Class registered for archive must be default constructible"); ClassArchiveInfo info; info.creator = [this,&info](const std::type_info& ti) -> void* - { return typeid(T) == ti ? new T : Caster::tryUpcast(ti, new T); }; + { return typeid(T) == ti ? constructIfPossible() + : Caster::tryUpcast(ti, constructIfPossible()); }; info.upcaster = [this](const std::type_info& ti, void* p) -> void* { return typeid(T) == ti ? p : Caster::tryUpcast(ti, (T*) p); }; info.downcaster = [this](const std::type_info& ti, void* p) -> void* diff --git a/libsrc/csg/csgeom.cpp b/libsrc/csg/csgeom.cpp index 3226e538..3662966d 100644 --- a/libsrc/csg/csgeom.cpp +++ b/libsrc/csg/csgeom.cpp @@ -326,9 +326,9 @@ namespace netgen void CSGeometry :: DoArchive(Archive& archive) { - archive & surfaces & surf2prim & solids & toplevelobjects & userpoints & userpoints_ref_factor + archive & surfaces & solids & toplevelobjects & userpoints & userpoints_ref_factor & identpoints & boundingbox & identicsurfaces & isidenticto & ideps - & filename & spline_surfaces; // TODO: & splinecurves2d & splinecurves3d + & filename & spline_surfaces; // TODO: & splinecurves2d & splinecurves3d & surf2prim } void CSGeometry :: SaveSurfaces (ostream & out) const diff --git a/libsrc/csg/csgeom.hpp b/libsrc/csg/csgeom.hpp index ee9e1260..ab91b08a 100644 --- a/libsrc/csg/csgeom.hpp +++ b/libsrc/csg/csgeom.hpp @@ -40,6 +40,11 @@ namespace netgen TopLevelObject (Solid * asolid, Surface * asurface = NULL); + void DoArchive(Archive& archive) + { + archive & solid & surface & red & blue & green & visible & transp & maxh + & material & layer & bc & bcname; + } const Solid * GetSolid() const { return solid; } Solid * GetSolid() { return solid; } diff --git a/libsrc/csg/solid.hpp b/libsrc/csg/solid.hpp index 724030bd..928f8985 100644 --- a/libsrc/csg/solid.hpp +++ b/libsrc/csg/solid.hpp @@ -57,6 +57,18 @@ namespace netgen Solid (optyp aop, Solid * as1, Solid * as2 = NULL); ~Solid (); + void DoArchive(Archive& archive) + { + archive & name & prim & s1 & s2 & visited & maxh & num_surfs; + if(archive.Output()) + archive << int(op); + else + { + int iop; + archive & iop; + op = optyp(iop); + } + } const char * Name () const { return name; } void SetName (const char * aname); diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index dc31be16..40ee202b 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -13,6 +13,7 @@ public: virtual void DoArchive(Archive& archive) { archive & a; } }; +// pure abstract base class class SharedPtrHolder : virtual public CommonBase { public: @@ -20,6 +21,7 @@ public: virtual ~SharedPtrHolder() { } + virtual void abstract() = 0; virtual void DoArchive(Archive& archive) { CommonBase::DoArchive(archive); @@ -49,6 +51,7 @@ public: SharedPtrHolder::DoArchive(archive); PtrHolder::DoArchive(archive); } + virtual void abstract() {} }; // Classes without virt. or multiple inheritance do not need to be registered @@ -91,12 +94,12 @@ void testSharedPointer(Archive& in, Archive& out) SECTION("Same shared ptr") { static_assert(has_DoArchive::value, ""); - SharedPtrHolder holder, holder2; + SharedPtrAndPtrHolder holder, holder2; holder.names.push_back(make_shared("name")); holder2.names = holder.names; // same shared ptr out & holder & holder2; out.FlushBuffer(); - SharedPtrHolder inholder, inholder2; + SharedPtrAndPtrHolder inholder, inholder2; in & inholder & inholder2; CHECK(inholder.names.size() == 1); CHECK(inholder.names[0] == inholder2.names[0]); From e4d6ff8302416051fa56d0a55ef202c6dcdfe2b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Tue, 4 Dec 2018 06:58:08 +0100 Subject: [PATCH 10/46] point-sources in 2D --- libsrc/geom2d/genmesh2d.cpp | 19 ++++++++++++++++++- libsrc/geom2d/python_geom2d.cpp | 5 +++-- libsrc/gprim/spline.hpp | 3 ++- libsrc/include/nginterface_v2_impl.hpp | 1 + libsrc/meshing/adfront2.cpp | 4 ++-- libsrc/meshing/meshtype.hpp | 1 + 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/libsrc/geom2d/genmesh2d.cpp b/libsrc/geom2d/genmesh2d.cpp index 208d0c2b..54dc5691 100644 --- a/libsrc/geom2d/genmesh2d.cpp +++ b/libsrc/geom2d/genmesh2d.cpp @@ -207,6 +207,9 @@ namespace netgen // mesh size restrictions ... + + for (auto & point : geompoints) + mesh2d.RestrictLocalH (Point<3> (point(0), point(1), 0), point.hmax); for (int i = 0; i < splines.Size(); i++) { @@ -240,7 +243,21 @@ namespace netgen for (auto mspnt : mp.meshsize_points) mesh2d.RestrictLocalH (mspnt.pnt, mspnt.h); - + + // add point elements + for (auto & point : geompoints) + if (point.name.length()) + { + Point<3> newp(point(0), point(1), 0); + PointIndex npi = mesh2d.AddPoint (newp, 1, FIXEDPOINT); + mesh2d.AddLockedPoint(npi); + Element0d el(npi, npi); + el.name = point.name; + mesh2d.SetCD2Name(npi, point.name); + mesh2d.pointelements.Append (el); + searchtree.Insert (newp, npi); + } + // first add all vertices (for compatible orientation on periodic bnds) { double diam2 = Dist2(pmin, pmax); diff --git a/libsrc/geom2d/python_geom2d.cpp b/libsrc/geom2d/python_geom2d.cpp index f44b525e..d6abe3b8 100644 --- a/libsrc/geom2d/python_geom2d.cpp +++ b/libsrc/geom2d/python_geom2d.cpp @@ -31,7 +31,7 @@ DLL_HEADER void ExportGeom2d(py::module &m) .def("Load",&SplineGeometry2d::Load) .def("AppendPoint", FunctionPointer - ([](SplineGeometry2d &self, double px, double py, double maxh, double hpref) + ([](SplineGeometry2d &self, double px, double py, double maxh, double hpref, string name) { Point<2> p; p(0) = px; @@ -39,10 +39,11 @@ DLL_HEADER void ExportGeom2d(py::module &m) GeomPoint<2> gp(p); gp.hmax = maxh; gp.hpref = hpref; + gp.name = name; self.geompoints.Append(gp); return self.geompoints.Size()-1; }), - py::arg("x"), py::arg("y"), py::arg("maxh") = 1e99, py::arg("hpref")=0) + py::arg("x"), py::arg("y"), py::arg("maxh") = 1e99, py::arg("hpref")=0, py::arg("name")="") .def("Append", FunctionPointer([](SplineGeometry2d &self, py::list segment, int leftdomain, int rightdomain, py::object bc, py::object copy, double maxh, double hpref) { diff --git a/libsrc/gprim/spline.hpp b/libsrc/gprim/spline.hpp index a628d07d..e227a18a 100644 --- a/libsrc/gprim/spline.hpp +++ b/libsrc/gprim/spline.hpp @@ -28,7 +28,8 @@ namespace netgen double hmax; /// hp-refinement double hpref; - + /// + string name; /// GeomPoint () { ; } diff --git a/libsrc/include/nginterface_v2_impl.hpp b/libsrc/include/nginterface_v2_impl.hpp index aa538761..62e8068d 100644 --- a/libsrc/include/nginterface_v2_impl.hpp +++ b/libsrc/include/nginterface_v2_impl.hpp @@ -47,6 +47,7 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<0> (size_t nr) const Ng_Element ret; ret.type = NG_PNT; ret.index = el.index; + ret.mat = &el.name; ret.points.num = 1; ret.points.ptr = (int*)&el.pnum; diff --git a/libsrc/meshing/adfront2.cpp b/libsrc/meshing/adfront2.cpp index 7eb426ad..11dd7421 100644 --- a/libsrc/meshing/adfront2.cpp +++ b/libsrc/meshing/adfront2.cpp @@ -22,7 +22,7 @@ namespace netgen mgi = new MultiPointGeomInfo (*amgi); for (int i = 1; i <= mgi->GetNPGI(); i++) if (mgi->GetPGI(i).trignum <= 0) - cout << "Add FrontPoint2, illegal geominfo = " << mgi->GetPGI(i).trignum << endl; + cout << "WARNING: Add FrontPoint2, illegal geominfo = " << mgi->GetPGI(i).trignum << endl; } else mgi = NULL; @@ -136,7 +136,7 @@ namespace netgen if (!gi1.trignum || !gi2.trignum) { - cout << "ERROR: in AdFront::AddLine, illegal geominfo" << endl; + cout << "WARNING: in AdFront::AddLine, illegal geominfo" << endl; } lines[li].SetGeomInfo (gi1, gi2); diff --git a/libsrc/meshing/meshtype.hpp b/libsrc/meshing/meshtype.hpp index 5fe1d8a6..75a0946d 100644 --- a/libsrc/meshing/meshtype.hpp +++ b/libsrc/meshing/meshtype.hpp @@ -1062,6 +1062,7 @@ namespace netgen { public: PointIndex pnum; + string name; int index; Element0d () = default; Element0d (PointIndex _pnum, int _index) From 7b7e7a52b56d1b80594e1b35465edad57f0d872f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Tue, 4 Dec 2018 09:49:53 +0100 Subject: [PATCH 11/46] throw exception if 2d meshing fails --- libsrc/geom2d/genmesh2d.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libsrc/geom2d/genmesh2d.cpp b/libsrc/geom2d/genmesh2d.cpp index 54dc5691..43193e3a 100644 --- a/libsrc/geom2d/genmesh2d.cpp +++ b/libsrc/geom2d/genmesh2d.cpp @@ -601,8 +601,10 @@ namespace netgen // not complete, use at own risk ... // meshing.Delaunay(*mesh, domnr, mp); mp.checkoverlap = 0; - meshing.GenerateMesh (*mesh, mp, h, domnr); - + auto res = meshing.GenerateMesh (*mesh, mp, h, domnr); + if (res != 0) + throw NgException("meshing failed"); + for (SurfaceElementIndex sei = oldnf; sei < mesh->GetNSE(); sei++) (*mesh)[sei].SetIndex (domnr); From a1847ec05f34f418be143bb291e7408aa8c30daf Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Tue, 4 Dec 2018 11:13:12 +0100 Subject: [PATCH 12/46] store demangled type names for cross platform archive --- libsrc/core/basearchive.cpp | 11 +++++++++++ libsrc/core/basearchive.hpp | 35 ++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/libsrc/core/basearchive.cpp b/libsrc/core/basearchive.cpp index 434fbab5..1fb0d713 100644 --- a/libsrc/core/basearchive.cpp +++ b/libsrc/core/basearchive.cpp @@ -1,8 +1,19 @@ #include "ngcore.hpp" +#ifndef WIN +#include +#endif + namespace ngcore { +#ifdef WIN + // windows does demangling in typeid(T).name() + std::string demangle(const char* typeinfo) { return typeinfo; } +#else + std::string demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, 0, 0, &status); } +#endif + std::map& GetArchiveRegister() { static std::map type_register; diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index f16ef942..26ca217e 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -4,11 +4,12 @@ namespace ngcore { class Archive; + std::string demangle(const char* typeinfo); // create new pointer of type T if it is default constructible, else throw template T* constructIfPossible_impl(...) - { throw std::runtime_error(std::string(typeid(T).name()) + " is not default constructible!"); } + { throw std::runtime_error(std::string(demangle(typeid(T).name())) + " is not default constructible!"); } template::value>::type> T* constructIfPossible_impl(int) { return new T; } @@ -164,11 +165,11 @@ namespace ngcore // Downcasting is only possible for our registered classes if(typeid(T) != typeid(*ptr)) { - if(GetArchiveRegister().count(std::string(typeid(*ptr).name())) == 0) + if(GetArchiveRegister().count(demangle(typeid(*ptr).name())) == 0) throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + typeid(*ptr).name() + + demangle(typeid(*ptr).name()) + " not registered for archive"); - reg_ptr = GetArchiveRegister()[typeid(*ptr).name()].downcaster(typeid(T), ptr.get()); + reg_ptr = GetArchiveRegister()[demangle(typeid(*ptr).name())].downcaster(typeid(T), ptr.get()); // if there was a true downcast we have to store more information if(reg_ptr != (void*) ptr.get()) neededDowncast = true; @@ -182,14 +183,14 @@ namespace ngcore (*this) & neededDowncast & p; // if we did downcast we store the true type as well if(neededDowncast) - (*this) << std::string(typeid(*ptr).name()); + (*this) << demangle(typeid(*ptr).name()); shared_ptr2nr[reg_ptr] = shared_ptr_count++; return *this; } // if found store the position and if it has to be downcasted and how (*this) << pos->second << neededDowncast; if(neededDowncast) - (*this) << std::string(typeid(*ptr).name()); + (*this) << demangle(typeid(*ptr).name()); return (*this); } else // Input @@ -261,12 +262,12 @@ namespace ngcore void* reg_ptr = (void*)p; if(typeid(T) != typeid(*p)) { - if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) + if(GetArchiveRegister().count(demangle(typeid(*p).name())) == 0) throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + typeid(*p).name() + + demangle(typeid(*p).name()) + " not registered for archive"); else - reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), (void*) p); + reg_ptr = GetArchiveRegister()[demangle(typeid(*p).name())].downcaster(typeid(T), (void*) p); } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry @@ -280,19 +281,19 @@ namespace ngcore } else throw std::runtime_error(std::string("Archive error: Class ") + - typeid(*p).name() + " does not provide a default constructor!"); + demangle(typeid(*p).name()) + " does not provide a default constructor!"); else { // if a pointer to a base class is archived, the class hierarchy must be registered // to avoid compile time issues we allow this behaviour only for "our" classes that // implement a void DoArchive(Archive&) member function // To recreate the object we need to store the true type of it - if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) + if(GetArchiveRegister().count(demangle(typeid(*p).name())) == 0) throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + typeid(*p).name() + + demangle(typeid(*p).name()) + " not registered for archive"); else - return (*this) << -3 << std::string(typeid(*p).name()) & (*p); + return (*this) << -3 << demangle(typeid(*p).name()) & (*p); } } else @@ -300,7 +301,7 @@ namespace ngcore (*this) & pos->second; bool downcasted = !(reg_ptr == (void*) p); // store if the class has been downcasted and the name - (*this) << downcasted << std::string(typeid(*p).name()); + (*this) << downcasted << demangle(typeid(*p).name()); } } else @@ -373,7 +374,7 @@ namespace ngcore { return typeid(T) == ti ? p : Caster::tryUpcast(ti, (T*) p); }; info.downcaster = [this](const std::type_info& ti, void* p) -> void* { return typeid(T) == ti ? p : Caster::tryDowncast(ti, p); }; - GetArchiveRegister()[std::string(typeid(T).name())] = info; + GetArchiveRegister()[std::string(demangle(typeid(T).name()))] = info; } }; @@ -396,7 +397,7 @@ namespace ngcore static void* tryUpcast(const std::type_info& ti, T* p) { try - { return GetArchiveRegister()[typeid(B1).name()].upcaster(ti, (void*) (dynamic_cast(p))); } + { return GetArchiveRegister()[demangle(typeid(B1).name())].upcaster(ti, (void*) (dynamic_cast(p))); } catch(std::exception) { return Caster::tryUpcast(ti, p); } } @@ -406,7 +407,7 @@ namespace ngcore if(typeid(B1) == ti) return dynamic_cast((B1*) p); try - { return GetArchiveRegister()[typeid(B1).name()].downcaster(ti, (void*) ((B1*)p)); } + { return GetArchiveRegister()[demangle(typeid(B1).name())].downcaster(ti, (void*) ((B1*)p)); } catch(std::exception) { return Caster::tryDowncast(ti, p); } } From 292dbcf5a0a665f8bf02d4f69d7cb9f26f0b5d4e Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 5 Dec 2018 14:20:24 +0100 Subject: [PATCH 13/46] version checks for archive, fix archive of empty string --- libsrc/core/CMakeLists.txt | 2 +- libsrc/core/archive.hpp | 60 ++++++++++++++++++++------ libsrc/core/basearchive.cpp | 5 +++ libsrc/core/basearchive.hpp | 28 +++++++++++++ libsrc/core/ngcore.hpp | 5 +++ libsrc/core/version.hpp | 84 +++++++++++++++++++++++++++++++++++++ libsrc/csg/python_csg.cpp | 16 ++++--- tests/catch/CMakeLists.txt | 1 + tests/catch/archive.cpp | 22 ++++++++++ tests/catch/version.cpp | 19 +++++++++ 10 files changed, 219 insertions(+), 23 deletions(-) create mode 100644 libsrc/core/version.hpp create mode 100644 tests/catch/version.cpp diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 8b14b211..332740bb 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -5,6 +5,6 @@ set_target_properties(ngcore PROPERTIES POSITION_INDEPENDENT_CODE ON ) install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) -install(FILES ngcore.hpp archive.hpp basearchive.hpp +install(FILES ngcore.hpp archive.hpp basearchive.hpp version.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel ) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 7b213b8d..7da24f98 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -6,16 +6,22 @@ namespace ngcore // BinaryOutArchive ====================================================================== class BinaryOutArchive : public Archive { - std::shared_ptr fout; size_t ptr = 0; enum { BUFFERSIZE = 1024 }; char buffer[BUFFERSIZE]; + std::shared_ptr fout; public: - BinaryOutArchive (std::shared_ptr afout) : Archive(true), fout(afout) { ; } - BinaryOutArchive (std::string filename) + BinaryOutArchive(std::shared_ptr afout) : Archive(true), fout(afout) + { + (*this) & GetLibraryVersions(); + } + BinaryOutArchive(std::string filename) : BinaryOutArchive(std::make_shared(filename)) {} virtual ~BinaryOutArchive () { FlushBuffer(); } + const VersionInfo& getVersion(const std::string& library) + { return GetLibraryVersions()[library]; } + using Archive::operator&; virtual Archive & operator & (double & d) { return Write(d); } @@ -76,11 +82,18 @@ namespace ngcore // BinaryInArchive ====================================================================== class BinaryInArchive : public Archive { + std::map vinfo; std::shared_ptr fin; public: - BinaryInArchive (std::shared_ptr afin) : Archive(false), fin(afin) { ; } + BinaryInArchive (std::shared_ptr afin) : Archive(false), fin(afin) + { + (*this) & vinfo; + } BinaryInArchive (std::string filename) - : BinaryInArchive(std::make_shared(filename)) {} + : BinaryInArchive(std::make_shared(filename)) { ; } + + const VersionInfo& getVersion(const std::string& library) + { return vinfo[library]; } using Archive::operator&; virtual Archive & operator & (double & d) @@ -133,10 +146,16 @@ namespace ngcore { std::shared_ptr fout; public: - TextOutArchive (std::shared_ptr afout) : Archive(true), fout(afout) { } + TextOutArchive (std::shared_ptr afout) : Archive(true), fout(afout) + { + (*this) & GetLibraryVersions(); + } TextOutArchive (std::string filename) : TextOutArchive(std::make_shared(filename.c_str())) { } + const VersionInfo& getVersion(const std::string& library) + { return GetLibraryVersions()[library]; } + using Archive::operator&; virtual Archive & operator & (double & d) { *fout << d << '\n'; return *this; } @@ -156,16 +175,22 @@ namespace ngcore { int len = str.length(); *fout << len << '\n'; - fout->write(&str[0], len); - *fout << '\n'; + if(len) + { + fout->write(&str[0], len); + *fout << '\n'; + } return *this; } virtual Archive & operator & (char *& str) { int len = strlen (str); *fout << len << '\n'; - fout->write (&str[0], len); - *fout << '\n'; + if(len) + { + fout->write (&str[0], len); + *fout << '\n'; + } return *this; } }; @@ -173,12 +198,19 @@ namespace ngcore // TextInArchive ====================================================================== class TextInArchive : public Archive { + std::map vinfo; std::shared_ptr fin; public: - TextInArchive (std::shared_ptr afin) : Archive(false), fin(afin) { ; } + TextInArchive (std::shared_ptr afin) : Archive(false), fin(afin) + { + (*this) & vinfo; + } TextInArchive (std::string filename) : TextInArchive(std::make_shared(filename)) {} + const VersionInfo& getVersion(const std::string& library) + { return vinfo[library]; } + using Archive::operator&; virtual Archive & operator & (double & d) { *fin >> d; return *this; } @@ -201,7 +233,8 @@ namespace ngcore char ch; fin->get(ch); // '\n' str.resize(len); - fin->get(&str[0], len+1, '\0'); + if(len) + fin->get(&str[0], len+1, '\0'); return *this; } virtual Archive & operator & (char *& str) @@ -211,7 +244,8 @@ namespace ngcore char ch; fin->get(ch); // '\n' str = new char[len+1]; - fin->get(&str[0], len, '\0'); + if(len) + fin->get(&str[0], len, '\0'); str[len] = 0; return *this; } diff --git a/libsrc/core/basearchive.cpp b/libsrc/core/basearchive.cpp index 1fb0d713..975006fc 100644 --- a/libsrc/core/basearchive.cpp +++ b/libsrc/core/basearchive.cpp @@ -7,6 +7,11 @@ namespace ngcore { + std::map& GetLibraryVersions() + { + static std::map library_versions; + return library_versions; + } #ifdef WIN // windows does demangling in typeid(T).name() std::string demangle(const char* typeinfo) { return typeinfo; } diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index 26ca217e..9fdf95e0 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -3,6 +3,10 @@ namespace ngcore { + class VersionInfo; + // Libraries using this archive can store their version here to implement backwards compatibility + std::map& GetLibraryVersions(); + class Archive; std::string demangle(const char* typeinfo); @@ -75,6 +79,7 @@ namespace ngcore bool Output () { return is_output; } bool Input () { return !is_output; } + virtual const VersionInfo& getVersion(const std::string& library) = 0; // Pure virtual functions that have to be implemented by In-/OutArchive virtual Archive & operator & (double & d) = 0; @@ -116,6 +121,29 @@ namespace ngcore Do(&v[0], size); return (*this); } + template + Archive& operator& (std::map& map) + { + if(is_output) + { + (*this) << size_t(map.size()); + for(auto& pair : map) + (*this) << pair.first << pair.second; + } + else + { + size_t size; + (*this) & size; + T1 key; T2 val; + for(size_t i = 0; i < size; i++) + { + T1 key; T2 val; + (*this) & key & val; + map[key] = val; + } + } + return (*this); + } // Archive arrays ===================================================== // this functions can be overloaded in Archive implementations for more efficiency template diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index e93a506c..0a37c977 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -15,6 +16,8 @@ #include +namespace ngcore +{ #if defined(__GNUC__) inline bool likely (bool x) { return __builtin_expect((x), true); } inline bool unlikely (bool x) { return __builtin_expect((x), false); } @@ -22,9 +25,11 @@ inline bool likely (bool x) { return x; } inline bool unlikely (bool x) { return x; } #endif +} // own includes #include "basearchive.hpp" +#include "version.hpp" #include "archive.hpp" #endif // NG_CORE_HPP diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp new file mode 100644 index 00000000..bf11b3e9 --- /dev/null +++ b/libsrc/core/version.hpp @@ -0,0 +1,84 @@ + +namespace ngcore +{ + class VersionInfo + { + private: + size_t mayor, minor, date, commit_offset; + std::string git_hash; + public: + VersionInfo() : mayor(0), minor(0), date(0), commit_offset(0), git_hash("") {} + VersionInfo(std::string vstring) + { + minor = date = commit_offset = 0; + git_hash = ""; + if(vstring.substr(0,1) == "v") + vstring = vstring.substr(1,vstring.size()-1); + auto dot = vstring.find("."); + mayor = std::stoi(vstring.substr(0,dot)); + if(dot == size_t(-1)) vstring = ""; + else vstring = vstring.substr(dot+1, vstring.size()-dot-1); + if(vstring.size()) + { + dot = vstring.find("."); + minor = std::stoi(vstring.substr(0,dot)); + if (dot == size_t(-1)) vstring = ""; + else vstring = vstring.substr(dot+1, vstring.size()-dot-1); + if(vstring.size()) + { + dot = vstring.find("-"); + date = std::stoi(vstring.substr(0,dot)); + if(dot == size_t(-1)) vstring = ""; + else vstring = vstring.substr(dot+1,vstring.size()-dot-1); + if(vstring.size()) + { + dot = vstring.find("-"); + commit_offset = std::stoi(vstring.substr(0,dot)); + if(dot == size_t(-1)) vstring = ""; + else vstring = vstring.substr(dot+1, vstring.size()-dot-1); + if(vstring.size()) + git_hash = vstring; + } + } + } + } + VersionInfo(const char* cstr) : VersionInfo(std::string(cstr)) { } + + std::string to_string() const + { std::string vstring = "v" + std::to_string(mayor); + if(minor || date || commit_offset || git_hash.size()) + { + vstring += "." + std::to_string(minor); + if(date || commit_offset || git_hash.size()) + { + vstring += "." + std::to_string(date); + if(commit_offset || git_hash.size()) + { + vstring += "-" + std::to_string(commit_offset); + if(git_hash.size()) + vstring += "-" + git_hash; + } + } + } + return vstring; + } + bool operator <(const VersionInfo& other) const + { + return std::tie(mayor, minor, date, commit_offset) < + std::tie(other.mayor, other.minor, other.date, other.commit_offset); + } + bool operator ==(const VersionInfo& other) const + { + return mayor == other.mayor && minor == other.minor && date == other.date + && commit_offset == other.commit_offset; + } + bool operator >(const VersionInfo& other) const { return other < (*this); } + bool operator <=(const VersionInfo& other) const { return !((*this) > other); } + bool operator >=(const VersionInfo& other) const { return !((*this) < other); } + + void DoArchive(Archive& ar) + { + ar & mayor & minor & date & commit_offset & git_hash; + } + }; +} diff --git a/libsrc/csg/python_csg.cpp b/libsrc/csg/python_csg.cpp index 05ac4acc..e9895738 100644 --- a/libsrc/csg/python_csg.cpp +++ b/libsrc/csg/python_csg.cpp @@ -371,19 +371,17 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails! .def(py::pickle( [](CSGeometry& self) { - stringstream ss; - self.Save(ss); - cout << "pickle = " << endl << ss.str() << endl; - return py::make_tuple(ss.str()); + auto ss = make_shared(); + BinaryOutArchive archive(ss); + archive & self; + return py::make_tuple(ss->str()); }, [](py::tuple state) { auto geo = make_shared(); - auto val = py::cast(state[0]); - cout << "unpickle = " << endl << val << endl; - stringstream ss(py::cast(state[0])); - // geo->Load(ss); - // geo->FindIdenticSurfaces(1e-8 * geo->MaxSize()); + auto ss = make_shared (py::cast(state[0])); + BinaryInArchive archive(ss); + archive & (*geo); return geo; })) .def("Save", FunctionPointer([] (CSGeometry & self, string filename) diff --git a/tests/catch/CMakeLists.txt b/tests/catch/CMakeLists.txt index d980d7f8..53cacdda 100644 --- a/tests/catch/CMakeLists.txt +++ b/tests/catch/CMakeLists.txt @@ -27,4 +27,5 @@ macro(add_unit_test name sources) endmacro() add_unit_test(archive archive.cpp) +add_unit_test(version version.cpp) endif(ENABLE_UNIT_TESTS) diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index 40ee202b..f6fb4bc8 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -203,8 +203,24 @@ void testMultipleInheritance(Archive& in, Archive& out) } } +void testLibraryVersion(Archive& in, Archive& out) +{ + GetLibraryVersions()["netgen"] = "v6.2.1812"; + CHECK(in.getVersion("netgen") == "v6.2.1811"); + CHECK(out.getVersion("netgen") == "v6.2.1812"); +} + void testArchive(Archive& in, Archive& out) { + SECTION("Empty String") + { + out << string("") << 1; + out.FlushBuffer(); + string str; int i; + in & str & i; + CHECK(str == ""); + CHECK(i == 1); + } SECTION("SharedPtr") { testSharedPointer(in, out); @@ -226,10 +242,15 @@ void testArchive(Archive& in, Archive& out) { testNullPtr(in, out); } + SECTION("Library Version") + { + testLibraryVersion(in,out); + } } TEST_CASE("BinaryArchive") { + GetLibraryVersions()["netgen"] = "v6.2.1811"; auto stream = make_shared(); BinaryOutArchive out(stream); BinaryInArchive in(stream); @@ -238,6 +259,7 @@ TEST_CASE("BinaryArchive") TEST_CASE("TextArchive") { + GetLibraryVersions()["netgen"] = "v6.2.1811"; auto stream = make_shared(); TextOutArchive out(stream); TextInArchive in(stream); diff --git a/tests/catch/version.cpp b/tests/catch/version.cpp new file mode 100644 index 00000000..5655ab23 --- /dev/null +++ b/tests/catch/version.cpp @@ -0,0 +1,19 @@ + +#include "catch.hpp" +#include <../core/ngcore.hpp> +using namespace ngcore; +using namespace std; + + +TEST_CASE("Version") +{ + VersionInfo v("v6.2.1811-3-asdf"); + CHECK(v.to_string() == "v6.2.1811-3-asdf"); + VersionInfo v2("6.2"); + CHECK(v2.to_string() == "v6.2"); + CHECK(v < "v7"); + CHECK(v >= "6.2"); + CHECK(v > "6.2.1811"); + CHECK(v < "6.2.1811-5"); + CHECK(v == "v6.2.1811-3"); +} From ed494caa443f066a1f590a9a40f0916f07815b96 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Fri, 30 Nov 2018 13:40:30 +0100 Subject: [PATCH 14/46] [cmake] Build tkdnd with CMake and correct Tcl/Tk version --- cmake/external_projects/tcltk.cmake | 100 ++++++--------------- cmake/external_projects/tkdnd_macosx.patch | 69 +++++++------- 2 files changed, 60 insertions(+), 109 deletions(-) diff --git a/cmake/external_projects/tcltk.cmake b/cmake/external_projects/tcltk.cmake index 06852df1..7b174a7c 100644 --- a/cmake/external_projects/tcltk.cmake +++ b/cmake/external_projects/tcltk.cmake @@ -27,85 +27,35 @@ if(APPLE) set(TCL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tcl) set(TK_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tk) - set(TCL_INCLUDE_PATH ${TCL_DIR}/generic;${TCL_DIR}/macosx) - set(TK_INCLUDE_PATH ${TK_DIR}/generic;${TK_DIR}/macosx;${TK_DIR}/xlib) - find_package(TCL 8.6 REQUIRED) - list(APPEND NETGEN_DEPENDENCIES project_tcl project_tk) + set(TCL_INCLUDE_PATH "${TCL_DIR}/generic;${TCL_DIR}/macosx") + set(TK_INCLUDE_PATH "${TK_DIR}/generic;${TK_DIR}/macosx;${TK_DIR}/xlib") + string(REPLACE ";" "$" TCL_INC "${TCL_INCLUDE_PATH}") + string(REPLACE ";" "$" TK_INC "${TK_INCLUDE_PATH}") + ExternalProject_Add(project_tkdnd + URL "http://sourceforge.net/projects/tkdnd/files/TkDND/TkDND%202.8/tkdnd2.8-src.tar.gz" + URL_MD5 a6d47a996ea957416469b12965d4db91 + DEPENDS project_tcl project_tk + DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies + PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_LIST_DIR}/tkdnd_macosx.patch + UPDATE_COMMAND "" # Disable update + BUILD_IN_SOURCE 1 + CMAKE_ARGS + -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/Contents/MacOS + -DTCL_INCLUDE_PATH=${TCL_INC} + -DTK_INCLUDE_PATH=${TK_INC} + -DTK_LIBRARY=${TK_LIBRARY} + -DTCL_LIBRARY=${TCL_LIBRARY} + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 + ) + +list(APPEND NETGEN_DEPENDENCIES project_tkdnd) else() find_package(TCL 8.5 REQUIRED) endif() -# set(HOME $ENV{HOME}) -# set(tcl_prefix ${CMAKE_INSTALL_PREFIX}/../../) -# ExternalProject_Add(project_tcl -# URL "http://sourceforge.net/projects/tcl/files/Tcl/8.6.4/tcl8.6.4-src.tar.gz" -# URL_MD5 d7cbb91f1ded1919370a30edd1534304 -# DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies -# UPDATE_COMMAND "" # Disable update -# CONFIGURE_COMMAND ../project_tcl/macosx/configure --enable-threads --enable-framework --prefix=${tcl_prefix} --libdir=${tcl_prefix}/Contents/Frameworks --bindir=${tcl_prefix}/Contents/Frameworks/Tcl.framework/bin -# BUILD_COMMAND make -j4 binaries libraries -# INSTALL_COMMAND make install-binaries install-headers install-libraries install-private-headers -# LOG_DOWNLOAD 1 -# LOG_BUILD 1 -# LOG_CONFIGURE 1 -# LOG_INSTALL 1 -# ) -# -# ExternalProject_Add(project_tk -# DEPENDS project_tcl -# URL "http://sourceforge.net/projects/tcl/files/Tcl/8.6.4/tk8.6.4-src.tar.gz" -# URL_MD5 261754d7dc2a582f00e35547777e1fea -# DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies -# UPDATE_COMMAND "" # Disable update -# CONFIGURE_COMMAND ../project_tk/macosx/configure --enable-aqua=yes --enable-threads --enable-framework --prefix=${tcl_prefix} --libdir=${tcl_prefix}/Contents/Frameworks --bindir=${tcl_prefix}/Contents/Frameworks/Tcl.framework/bin --with-tcl=${tcl_prefix}/Contents/Frameworks/Tcl.framework -# BUILD_COMMAND make -j4 binaries libraries -# INSTALL_COMMAND make install-binaries install-headers install-libraries install-private-headers -# LOG_DOWNLOAD 1 -# LOG_BUILD 1 -# LOG_CONFIGURE 1 -# LOG_INSTALL 1 -# ) -# -# ExternalProject_Add(project_tkdnd -# URL "https://sourceforge.net/projects/tkdnd/files/OS%20X%20Binaries/TkDND%202.8/tkdnd2.8-OSX-MountainLion.tar.gz" -# URL_MD5 2dbb471b1d66c5f391f3c3c5b71548fb -# DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies -# BUILD_IN_SOURCE 1 -# CONFIGURE_COMMAND "" -# BUILD_COMMAND "" -# INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}/../MacOS -# LOG_DOWNLOAD 1 -# LOG_CONFIGURE 1 -# LOG_BUILD 1 -# LOG_INSTALL 1 -# ) -# -# list(APPEND NETGEN_DEPENDENCIES project_tcl project_tk project_tkdnd) -# list(APPEND CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}../Frameworks) -# set(TCL_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/../Frameworks/Tcl.framework/Headers) -# set(TCL_LIBRARY ${CMAKE_INSTALL_PREFIX}/../Frameworks/Tcl.framework) -# set(TK_LIBRARY ${CMAKE_INSTALL_PREFIX}/../Frameworks/Tk.framework) -# set(TK_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/../Frameworks/Tk.framework/Headers) -# - - - -ExternalProject_Add(project_tkdnd - URL "http://sourceforge.net/projects/tkdnd/files/TkDND/TkDND%202.8/tkdnd2.8-src.tar.gz" - URL_MD5 a6d47a996ea957416469b12965d4db91 - DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies - PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_LIST_DIR}/tkdnd_macosx.patch - UPDATE_COMMAND "" # Disable update - BUILD_IN_SOURCE 1 - CONFIGURE_COMMAND ./configure --prefix=${CMAKE_INSTALL_PREFIX}/Contents/MacOS --libdir=${CMAKE_INSTALL_PREFIX}/Contents/MacOS - BUILD_COMMAND make - INSTALL_COMMAND make install - LOG_DOWNLOAD 1 - LOG_CONFIGURE 1 - LOG_BUILD 1 - LOG_INSTALL 1 -) -list(APPEND NETGEN_DEPENDENCIES project_tkdnd) elseif(WIN32) diff --git a/cmake/external_projects/tkdnd_macosx.patch b/cmake/external_projects/tkdnd_macosx.patch index a2ed4217..e6af1974 100644 --- a/cmake/external_projects/tkdnd_macosx.patch +++ b/cmake/external_projects/tkdnd_macosx.patch @@ -1,35 +1,36 @@ -diff -Naur orig/tkdnd2.8/configure changed/tkdnd2.8/configure ---- tkdnd2.8/configure 2015-05-13 19:24:32.000000000 +0200 -+++ tkdnd2.8/configure 2016-02-22 15:26:37.000000000 +0100 -@@ -6145,7 +6145,7 @@ - - - -- PKG_CFLAGS="$PKG_CFLAGS -DMAC_TK_COCOA -std=gnu99 -x objective-c -fobjc-gc" -+ PKG_CFLAGS="$PKG_CFLAGS -DMAC_TK_COCOA -std=gnu99 -x objective-c" - - - -diff -Naur orig/tkdnd2.8/configure.in changed/tkdnd2.8/configure.in ---- tkdnd2.8/configure.in 2015-05-13 19:24:32.000000000 +0200 -+++ tkdnd2.8/configure.in 2016-02-22 15:26:44.000000000 +0100 -@@ -126,7 +126,7 @@ - - if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then - TEA_ADD_SOURCES([macosx/macdnd.m]) -- TEA_ADD_CFLAGS([-DMAC_TK_COCOA -std=gnu99 -x objective-c -fobjc-gc]) -+ TEA_ADD_CFLAGS([-DMAC_TK_COCOA -std=gnu99 -x objective-c]) - TEA_ADD_LIBS([-framework Cocoa -framework Carbon]) - fi - -diff -Naur orig/tkdnd2.8/macosx/macdnd.m changed/tkdnd2.8/macosx/macdnd.m ---- tkdnd2.8/macosx/macdnd.m 2015-07-06 21:49:14.000000000 +0200 -+++ tkdnd2.8/macosx/macdnd.m 2016-02-22 15:27:04.000000000 +0100 -@@ -16,6 +16,7 @@ - #import - #import - #import -+#undef panic - #import - #import +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 4eb497c..c6424fc 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -43,17 +43,17 @@ IF ( WIN32 ) + ELSE ( WIN32 ) + ## Unix and OS X... + IF ( APPLE ) +- SET ( CMAKE_OSX_ARCHITECTURES "x86_64;i386" ) ++ SET ( CMAKE_OSX_ARCHITECTURES "x86_64") + FIND_LIBRARY ( COCOA_LIBRARY Cocoa ) + INCLUDE_DIRECTORIES ( macosx ) +- INCLUDE_DIRECTORIES ( /Library/Frameworks/Tk.framework/Versions/8.6/PrivateHeaders ) +- INCLUDE_DIRECTORIES ( /System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/tk-private ) +- INCLUDE_DIRECTORIES ( /System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/tk-private ) ++# INCLUDE_DIRECTORIES ( /Library/Frameworks/Tk.framework/Versions/8.6/PrivateHeaders ) ++# INCLUDE_DIRECTORIES ( /System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/tk-private ) ++# INCLUDE_DIRECTORIES ( /System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/tk-private ) + ADD_DEFINITIONS ( -DMAC_TK_COCOA -DMAC_OSX_TK) + ADD_DEFINITIONS ( -DMAC_OSX_TK ) + ADD_DEFINITIONS ( -std=gnu99 ) + ADD_DEFINITIONS ( -x objective-c ) +- ADD_DEFINITIONS ( -fobjc-gc ) ++# ADD_DEFINITIONS ( -fobjc-gc ) + ADD_DEFINITIONS ( -fno-objc-arc ) + # ADD_DEFINITIONS ( -fobjc-arc ) + LINK_LIBRARIES ( ${COCOA_LIBRARY} ) +@@ -125,7 +125,7 @@ SET ( CP ${CMAKE_COMMAND} -E copy ) + ## Locate Tcl/Tk + ## =========================================================================== + MESSAGE ( STATUS "Searching for Tcl/Tk..." ) +-FIND_PACKAGE ( TCL REQUIRED ) ++#FIND_PACKAGE ( TCL REQUIRED ) + FIND_PACKAGE ( TclStub REQUIRED ) + ## Tcl/Tk info (useful for debug purposes)... From fdfb596e9cc533914b715b9db9deff421372a245 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Thu, 6 Dec 2018 17:53:44 +0100 Subject: [PATCH 15/46] archive for CSGeometry --- libsrc/core/CMakeLists.txt | 2 +- libsrc/core/archive.hpp | 59 +++++++++++++++--------- libsrc/core/basearchive.cpp | 10 +++- libsrc/core/basearchive.hpp | 15 +++++- libsrc/core/ngcore.hpp | 1 + libsrc/core/type_traits.hpp | 8 ++++ libsrc/core/version.hpp | 30 ++++++------ libsrc/csg/algprim.cpp | 11 ++++- libsrc/csg/algprim.hpp | 67 +++++++++++++++++++++++++++ libsrc/csg/brick.cpp | 4 ++ libsrc/csg/brick.hpp | 26 ++++++++++- libsrc/csg/csgeom.cpp | 6 ++- libsrc/csg/csgeom.hpp | 2 + libsrc/csg/extrusion.cpp | 11 +++-- libsrc/csg/extrusion.hpp | 25 ++++++++-- libsrc/csg/python_csg.cpp | 5 +- libsrc/csg/revolution.cpp | 21 +++++---- libsrc/csg/revolution.hpp | 20 ++++++-- libsrc/csg/solid.hpp | 2 + libsrc/csg/surface.cpp | 4 ++ libsrc/geom2d/geom2dmesh.cpp | 4 +- libsrc/geom2d/geometry2d.hpp | 36 +++++++++------ libsrc/gprim/spline.cpp | 13 +++--- libsrc/gprim/spline.hpp | 36 +++++++++++++++ libsrc/gprim/splinegeometry.hpp | 4 ++ libsrc/linalg/vector.hpp | 8 ++++ tests/catch/archive.cpp | 82 ++++++++++++++++++++++++++------- tests/pytest/test_pickling.py | 40 ++++++++++++++++ 28 files changed, 444 insertions(+), 108 deletions(-) create mode 100644 libsrc/core/type_traits.hpp create mode 100644 tests/pytest/test_pickling.py diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 332740bb..04efdf01 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -5,6 +5,6 @@ set_target_properties(ngcore PROPERTIES POSITION_INDEPENDENT_CODE ON ) install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) -install(FILES ngcore.hpp archive.hpp basearchive.hpp version.hpp +install(FILES ngcore.hpp archive.hpp basearchive.hpp version.hpp type_traits.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel ) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 7da24f98..4a25748c 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -39,18 +39,20 @@ namespace ngcore { return Write(b); } virtual Archive & operator & (std::string & str) { - if (ptr > 0) FlushBuffer(); int len = str.length(); - fout->write (reinterpret_cast(&len), sizeof(int)); - fout->write (&str[0], len); + (*this) & len; + FlushBuffer(); + if(len) + fout->write (&str[0], len); return *this; } virtual Archive & operator & (char *& str) { - if (ptr > 0) FlushBuffer(); - int len = strlen (str); - fout->write (reinterpret_cast(&len), sizeof(int)); - fout->write (&str[0], len); + long len = str ? strlen (str) : -1; + (*this) & len; + FlushBuffer(); + if(len > 0) + fout->write (&str[0], len); return *this; } void FlushBuffer() @@ -113,18 +115,24 @@ namespace ngcore virtual Archive & operator & (std::string & str) { int len; - Read(len); + (*this) & len; str.resize(len); - fin->read(&str[0], len); + if(len) + fin->read(&str[0], len); return *this; } virtual Archive & operator & (char *& str) { - int len; - Read(len); - str = new char[len+1]; - fin->read(&str[0], len); - str[len] = '\0'; + long len; + (*this) & len; + if(len == -1) + str = nullptr; + else + { + str = new char[len+1]; + fin->read(&str[0], len); + str[len] = '\0'; + } return *this; } @@ -184,9 +192,9 @@ namespace ngcore } virtual Archive & operator & (char *& str) { - int len = strlen (str); - *fout << len << '\n'; - if(len) + long len = str ? strlen (str) : -1; + *this & len; + if(len > 0) { fout->write (&str[0], len); *fout << '\n'; @@ -239,14 +247,21 @@ namespace ngcore } virtual Archive & operator & (char *& str) { - int len; - *fin >> len; + long len; + (*this) & len; char ch; - fin->get(ch); // '\n' + if(len == -1) + { + str = nullptr; + return (*this); + } str = new char[len+1]; if(len) - fin->get(&str[0], len, '\0'); - str[len] = 0; + { + fin->get(ch); // \n + fin->get(&str[0], len+1, '\0'); + } + str[len] = '\0'; return *this; } }; diff --git a/libsrc/core/basearchive.cpp b/libsrc/core/basearchive.cpp index 975006fc..30f493bb 100644 --- a/libsrc/core/basearchive.cpp +++ b/libsrc/core/basearchive.cpp @@ -7,11 +7,17 @@ namespace ngcore { - std::map& GetLibraryVersions() + static std::map library_versions; + std::map& Archive :: GetLibraryVersions() { - static std::map library_versions; return library_versions; } + VersionInfo GetLibraryVersion(const std::string& library) + { return library_versions[library]; } + + void SetLibraryVersion(const std::string& library, VersionInfo version) + { library_versions[library] = version; } + #ifdef WIN // windows does demangling in typeid(T).name() std::string demangle(const char* typeinfo) { return typeinfo; } diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index 9fdf95e0..249c6e22 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -5,7 +5,8 @@ namespace ngcore { class VersionInfo; // Libraries using this archive can store their version here to implement backwards compatibility - std::map& GetLibraryVersions(); + VersionInfo GetLibraryVersion(const std::string& library); + void SetLibraryVersion(const std::string& library, VersionInfo version); class Archive; std::string demangle(const char* typeinfo); @@ -376,6 +377,13 @@ namespace ngcore return *this; } + // const ptr + template + Archive& operator &(const T*& t) + { + return (*this) & const_cast(t); + } + // Write a read only variable template Archive & operator << (const T & t) @@ -386,6 +394,9 @@ namespace ngcore } virtual void FlushBuffer() {} + + protected: + static std::map& GetLibraryVersions(); }; template @@ -394,6 +405,8 @@ namespace ngcore public: RegisterClassForArchive() { + static_assert(all_of_tmpl::value...>, + "Variadic template arguments must be base classes of T"); ClassArchiveInfo info; info.creator = [this,&info](const std::type_info& ti) -> void* { return typeid(T) == ti ? constructIfPossible() diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index 0a37c977..9d600991 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -28,6 +28,7 @@ namespace ngcore } // own includes +#include "type_traits.hpp" #include "basearchive.hpp" #include "version.hpp" #include "archive.hpp" diff --git a/libsrc/core/type_traits.hpp b/libsrc/core/type_traits.hpp new file mode 100644 index 00000000..3d515c08 --- /dev/null +++ b/libsrc/core/type_traits.hpp @@ -0,0 +1,8 @@ + + +namespace ngcore +{ + template struct _BoolArray{}; + template + constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(T || true)...>>::value; +} diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp index bf11b3e9..81932695 100644 --- a/libsrc/core/version.hpp +++ b/libsrc/core/version.hpp @@ -4,13 +4,13 @@ namespace ngcore class VersionInfo { private: - size_t mayor, minor, date, commit_offset; + size_t mayor, minor, release, patch; std::string git_hash; public: - VersionInfo() : mayor(0), minor(0), date(0), commit_offset(0), git_hash("") {} + VersionInfo() : mayor(0), minor(0), release(0), patch(0), git_hash("") {} VersionInfo(std::string vstring) { - minor = date = commit_offset = 0; + minor = release = patch = 0; git_hash = ""; if(vstring.substr(0,1) == "v") vstring = vstring.substr(1,vstring.size()-1); @@ -27,13 +27,13 @@ namespace ngcore if(vstring.size()) { dot = vstring.find("-"); - date = std::stoi(vstring.substr(0,dot)); + release = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1,vstring.size()-dot-1); if(vstring.size()) { dot = vstring.find("-"); - commit_offset = std::stoi(vstring.substr(0,dot)); + patch = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1, vstring.size()-dot-1); if(vstring.size()) @@ -46,15 +46,15 @@ namespace ngcore std::string to_string() const { std::string vstring = "v" + std::to_string(mayor); - if(minor || date || commit_offset || git_hash.size()) + if(minor || release || patch || git_hash.size()) { vstring += "." + std::to_string(minor); - if(date || commit_offset || git_hash.size()) + if(release || patch || git_hash.size()) { - vstring += "." + std::to_string(date); - if(commit_offset || git_hash.size()) + vstring += "." + std::to_string(release); + if(patch || git_hash.size()) { - vstring += "-" + std::to_string(commit_offset); + vstring += "-" + std::to_string(patch); if(git_hash.size()) vstring += "-" + git_hash; } @@ -64,13 +64,13 @@ namespace ngcore } bool operator <(const VersionInfo& other) const { - return std::tie(mayor, minor, date, commit_offset) < - std::tie(other.mayor, other.minor, other.date, other.commit_offset); + return std::tie(mayor, minor, release, patch) < + std::tie(other.mayor, other.minor, other.release, other.patch); } bool operator ==(const VersionInfo& other) const { - return mayor == other.mayor && minor == other.minor && date == other.date - && commit_offset == other.commit_offset; + return mayor == other.mayor && minor == other.minor && release == other.release + && patch == other.patch; } bool operator >(const VersionInfo& other) const { return other < (*this); } bool operator <=(const VersionInfo& other) const { return !((*this) > other); } @@ -78,7 +78,7 @@ namespace ngcore void DoArchive(Archive& ar) { - ar & mayor & minor & date & commit_offset & git_hash; + ar & mayor & minor & release & patch & git_hash; } }; } diff --git a/libsrc/csg/algprim.cpp b/libsrc/csg/algprim.cpp index 30dd780e..c324e460 100644 --- a/libsrc/csg/algprim.cpp +++ b/libsrc/csg/algprim.cpp @@ -1941,6 +1941,13 @@ void EllipticCone :: GetTriangleApproximation << R << " " << r << endl; } - - +RegisterClassForArchive regqs; +RegisterClassForArchive regpl; +RegisterClassForArchive regsph; +RegisterClassForArchive regcyl; +RegisterClassForArchive regelcyl; +RegisterClassForArchive regell; +RegisterClassForArchive regcone; +RegisterClassForArchive regellcone; +RegisterClassForArchive regtorus; } diff --git a/libsrc/csg/algprim.hpp b/libsrc/csg/algprim.hpp index 98715fd3..ab496cc7 100644 --- a/libsrc/csg/algprim.hpp +++ b/libsrc/csg/algprim.hpp @@ -47,6 +47,11 @@ namespace netgen virtual void Print (ostream & str) const; virtual void Read (istream & ist); void PrintCoeff (ostream & ost) const; + virtual void DoArchive(Archive& ar) + { + OneSurfacePrimitive::DoArchive(ar); + ar & cxx & cyy & czz & cxy & cxz & cyz & cx & cy & cz & c1; + } }; @@ -64,6 +69,14 @@ namespace netgen public: /// Plane (const Point<3> & ap, Vec<3> an); + // default constructor for archive + Plane() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & p & n & eps_base; + } Point<3> P() const { return p; } Vec<3> N() const { return n; } virtual void GetPrimitiveData (const char *& classname, @@ -130,6 +143,14 @@ namespace netgen public: /// Sphere (const Point<3> & ac, double ar); + // default constructor for archive + Sphere() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & c & r & invr; + } virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; @@ -188,6 +209,14 @@ namespace netgen public: Cylinder (const Point<3> & aa, const Point<3> & ab, double ar); Cylinder (Array & coeffs); + // default constructor for archive + Cylinder() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & b & r & vab; + } Point<3> A() const { return a; } Point<3> B() const { return b; } double R() const { return r; } @@ -250,7 +279,14 @@ namespace netgen EllipticCylinder (const Point<3> & aa, const Vec<3> & avl, const Vec<3> & avs); EllipticCylinder (Array & coeffs); + // default constructor for archive + EllipticCylinder() {} + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & vl & vs & vab & t0vec & t1vec & vabl & t0 & t1; + } // static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; @@ -299,6 +335,14 @@ namespace netgen const Vec<3> & av1, const Vec<3> & av2, const Vec<3> & av3); + // default constructor for archive + Ellipsoid() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & v1 & v2 & v3 & rmin; + } /// virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// @@ -339,6 +383,14 @@ namespace netgen /// Cone (const Point<3> & aa, const Point<3> & ab, double ara, double arb); /// + // default constructor for archive + Cone() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & b & ra & rb & minr & vab & t0vec & t1vec & vabl & t0 & t1 & cosphi; + } static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); @@ -383,7 +435,14 @@ namespace netgen /// EllipticCone (const Point<3> & aa, const Vec<3> & avl, const Vec<3> & avs, double ah, double avlr); + // default constructor for archive + EllipticCone() {} + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & vl & vs & h & vlr; + } static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); @@ -425,6 +484,14 @@ namespace netgen public: /// OK Torus (const Point<3> & ac, const Vec<3> & an, double aR, double ar); + // default constructor for archive + Torus() {} + + virtual void DoArchive(Archive& ar) + { + OneSurfacePrimitive::DoArchive(ar); + ar & c & n & R & r; + } /// OK const Point<3> & Center () const { return c; } /// OK diff --git a/libsrc/csg/brick.cpp b/libsrc/csg/brick.cpp index 54c23b17..b9508fba 100644 --- a/libsrc/csg/brick.cpp +++ b/libsrc/csg/brick.cpp @@ -523,4 +523,8 @@ void OrthoBrick :: Reduce (const BoxSphere<3> & box) surfaceactive.Elem(6) = (box.PMin()(0) < pmax(0)) && (pmax(0) < box.PMax()(0)); } + +RegisterClassForArchive regpar; +RegisterClassForArchive regbrick; +RegisterClassForArchive regob; } diff --git a/libsrc/csg/brick.hpp b/libsrc/csg/brick.hpp index 25b003e0..7db7b02d 100644 --- a/libsrc/csg/brick.hpp +++ b/libsrc/csg/brick.hpp @@ -28,8 +28,16 @@ namespace netgen public: Parallelogram3d (Point<3> ap1, Point<3> ap2, Point<3> ap3); + // default constructor for archive + Parallelogram3d() {} virtual ~Parallelogram3d (); + virtual void DoArchive(Archive& ar) + { + Surface::DoArchive(ar); + ar & p1 & p2 & p3 & p4 & v12 & v13 & n; + } + void SetPoints (Point<3> ap1, Point<3> ap2, Point<3> ap3); virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; @@ -60,7 +68,15 @@ namespace netgen public: Brick (Point<3> ap1, Point<3> ap2, Point<3> ap3, Point<3> ap4); + // default constructor for archive + Brick() {} virtual ~Brick (); + + virtual void DoArchive(Archive& ar) + { + Primitive::DoArchive(ar); + ar & p1 & p2 & p3 & p4 & v12 & v13 & v14 & faces; + } static Primitive * CreateDefault (); virtual Primitive * Copy () const; @@ -116,7 +132,15 @@ namespace netgen Point<3> pmin, pmax; public: OrthoBrick (const Point<3> & ap1, const Point<3> & ap2); - + // default constructor for archive + OrthoBrick() {} + + virtual void DoArchive(Archive& ar) + { + Brick::DoArchive(ar); + ar & pmin & pmax; + } + virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual void Reduce (const BoxSphere<3> & box); }; diff --git a/libsrc/csg/csgeom.cpp b/libsrc/csg/csgeom.cpp index 3662966d..b861d451 100644 --- a/libsrc/csg/csgeom.cpp +++ b/libsrc/csg/csgeom.cpp @@ -327,8 +327,10 @@ namespace netgen void CSGeometry :: DoArchive(Archive& archive) { archive & surfaces & solids & toplevelobjects & userpoints & userpoints_ref_factor - & identpoints & boundingbox & identicsurfaces & isidenticto & ideps - & filename & spline_surfaces; // TODO: & splinecurves2d & splinecurves3d & surf2prim + & identpoints & boundingbox & isidenticto & ideps + & filename & spline_surfaces & splinecurves2d & splinecurves3d & surf2prim; + if(archive.Input()) + FindIdenticSurfaces(1e-6); } void CSGeometry :: SaveSurfaces (ostream & out) const diff --git a/libsrc/csg/csgeom.hpp b/libsrc/csg/csgeom.hpp index ab91b08a..f1a8d8b6 100644 --- a/libsrc/csg/csgeom.hpp +++ b/libsrc/csg/csgeom.hpp @@ -39,6 +39,8 @@ namespace netgen public: TopLevelObject (Solid * asolid, Surface * asurface = NULL); + // default constructor for archive + TopLevelObject() {} void DoArchive(Archive& archive) { diff --git a/libsrc/csg/extrusion.cpp b/libsrc/csg/extrusion.cpp index 8b257c20..61446b0c 100644 --- a/libsrc/csg/extrusion.cpp +++ b/libsrc/csg/extrusion.cpp @@ -653,15 +653,15 @@ namespace netgen Extrusion :: Extrusion(const SplineGeometry<3> & path_in, const SplineGeometry<2> & profile_in, const Vec<3> & z_dir) : - path(path_in), profile(profile_in), z_direction(z_dir) + path(&path_in), profile(&profile_in), z_direction(z_dir) { surfaceactive.SetSize(0); surfaceids.SetSize(0); - for(int j=0; jGetNSplines(); j++) { - ExtrusionFace * face = new ExtrusionFace(&(profile.GetSpline(j)), - &path, + ExtrusionFace * face = new ExtrusionFace(&((*profile).GetSpline(j)), + path, z_direction); faces.Append(face); surfaceactive.Append(true); @@ -872,5 +872,6 @@ namespace netgen surfaceactive[i] = true; } - + RegisterClassForArchive regexf; + RegisterClassForArchive regextr; } diff --git a/libsrc/csg/extrusion.hpp b/libsrc/csg/extrusion.hpp index e80ac244..2d6b3bbe 100644 --- a/libsrc/csg/extrusion.hpp +++ b/libsrc/csg/extrusion.hpp @@ -49,9 +49,18 @@ namespace netgen const Vec<3> & z_direction); ExtrusionFace(const Array & raw_data); - + // default constructor for archive + ExtrusionFace() {} ~ExtrusionFace(); + + virtual void DoArchive(Archive& ar) + { + Surface::DoArchive(ar); + ar & profile & path & glob_z_direction & deletable & spline3_path & line_path & + x_dir & y_dir & z_dir & loc_z_dir & p0 & profile_tangent & profile_par & + profile_spline_coeff & latest_seg & latest_t & latest_point2d & latest_point3d; + } virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; @@ -109,10 +118,10 @@ namespace netgen class Extrusion : public Primitive { private: - const SplineGeometry<3> & path; - const SplineGeometry<2> & profile; // closed, clockwise oriented curve + const SplineGeometry<3>* path; + const SplineGeometry<2>* profile; // closed, clockwise oriented curve - const Vec<3> & z_direction; + Vec<3> z_direction; Array faces; @@ -122,7 +131,15 @@ namespace netgen Extrusion(const SplineGeometry<3> & path_in, const SplineGeometry<2> & profile_in, const Vec<3> & z_dir); + // default constructor for archive + Extrusion() {} ~Extrusion(); + + virtual void DoArchive(Archive& ar) + { + Primitive::DoArchive(ar); + ar & path & profile & z_direction & faces & latestfacenum; + } virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const; diff --git a/libsrc/csg/python_csg.cpp b/libsrc/csg/python_csg.cpp index e9895738..b84bb3e1 100644 --- a/libsrc/csg/python_csg.cpp +++ b/libsrc/csg/python_csg.cpp @@ -374,12 +374,13 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails! auto ss = make_shared(); BinaryOutArchive archive(ss); archive & self; - return py::make_tuple(ss->str()); + archive.FlushBuffer(); + return py::make_tuple(py::bytes(ss->str())); }, [](py::tuple state) { auto geo = make_shared(); - auto ss = make_shared (py::cast(state[0])); + auto ss = make_shared (py::cast(state[0])); BinaryInArchive archive(ss); archive & (*geo); return geo; diff --git a/libsrc/csg/revolution.cpp b/libsrc/csg/revolution.cpp index 4c13c109..dac2e277 100644 --- a/libsrc/csg/revolution.cpp +++ b/libsrc/csg/revolution.cpp @@ -640,9 +640,9 @@ namespace netgen Revolution :: Revolution(const Point<3> & p0_in, const Point<3> & p1_in, const SplineGeometry<2> & spline_in) : - p0(p0_in), p1(p1_in), splinecurve(spline_in), - nsplines(spline_in.GetNSplines()) + p0(p0_in), p1(p1_in) { + auto nsplines = spline_in.GetNSplines(); surfaceactive.SetSize(0); surfaceids.SetSize(0); @@ -650,21 +650,21 @@ namespace netgen v_axis.Normalize(); - if(splinecurve.GetSpline(0).StartPI()(1) <= 0. && - splinecurve.GetSpline(nsplines-1).EndPI()(1) <= 0.) + if(spline_in.GetSpline(0).StartPI()(1) <= 0. && + spline_in.GetSpline(nsplines-1).EndPI()(1) <= 0.) type = 2; - else if (Dist(splinecurve.GetSpline(0).StartPI(), - splinecurve.GetSpline(nsplines-1).EndPI()) < 1e-7) + else if (Dist(spline_in.GetSpline(0).StartPI(), + spline_in.GetSpline(nsplines-1).EndPI()) < 1e-7) type = 1; else cerr << "Surface of revolution cannot be constructed" << endl; - for(int i=0; i regrevf; + RegisterClassForArchive regrev; } diff --git a/libsrc/csg/revolution.hpp b/libsrc/csg/revolution.hpp index c9b4cb92..879829fd 100644 --- a/libsrc/csg/revolution.hpp +++ b/libsrc/csg/revolution.hpp @@ -45,9 +45,18 @@ namespace netgen const int id_in = 0); RevolutionFace(const Array & raw_data); + // default constructor for archive + RevolutionFace() {} ~RevolutionFace(); + virtual void DoArchive(Archive& ar) + { + Surface::DoArchive(ar); + ar & isfirst & islast & spline & deletable & p0 & v_axis & id & spline_coefficient + & spline_coefficient_shifted & checklines_vec & checklines_start & checklines_normal; + } + virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; virtual double CalcFunctionValue (const Point<3> & point) const; @@ -96,8 +105,6 @@ namespace netgen private: Point<3> p0,p1; Vec<3> v_axis; - const SplineGeometry<2> & splinecurve; - const int nsplines; // 1 ... torus-like // 2 ... sphere-like @@ -112,9 +119,16 @@ namespace netgen Revolution(const Point<3> & p0_in, const Point<3> & p1_in, const SplineGeometry<2> & spline_in); + // default constructor for archive + Revolution() {} ~Revolution(); - + + virtual void DoArchive(Archive& ar) + { + Primitive::DoArchive(ar); + ar & p0 & p1 & v_axis & type & faces & intersecting_face; + } /* Check, whether box intersects solid defined by surface. diff --git a/libsrc/csg/solid.hpp b/libsrc/csg/solid.hpp index 928f8985..4d620c04 100644 --- a/libsrc/csg/solid.hpp +++ b/libsrc/csg/solid.hpp @@ -55,6 +55,8 @@ namespace netgen public: Solid (Primitive * aprim); Solid (optyp aop, Solid * as1, Solid * as2 = NULL); + // default constructor for archive + Solid () {} ~Solid (); void DoArchive(Archive& archive) diff --git a/libsrc/csg/surface.cpp b/libsrc/csg/surface.cpp index db315e99..f829840b 100644 --- a/libsrc/csg/surface.cpp +++ b/libsrc/csg/surface.cpp @@ -566,4 +566,8 @@ void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp) if (Abs2 (rs) < 1e-24 && i > 1) i = 1; } } + +RegisterClassForArchive regsurf; +RegisterClassForArchive regprim; +RegisterClassForArchive regosf; } diff --git a/libsrc/geom2d/geom2dmesh.cpp b/libsrc/geom2d/geom2dmesh.cpp index 3de7f97f..be1fc6c9 100644 --- a/libsrc/geom2d/geom2dmesh.cpp +++ b/libsrc/geom2d/geom2dmesh.cpp @@ -47,8 +47,8 @@ namespace netgen auto ext = dynamic_cast(spline); if(ext) { - ss3 = dynamic_cast *>(&ext->seg); - ls = dynamic_cast *>(&ext->seg); + ss3 = dynamic_cast *>(ext->seg); + ls = dynamic_cast *>(ext->seg); } else { diff --git a/libsrc/geom2d/geometry2d.hpp b/libsrc/geom2d/geometry2d.hpp index ad02f754..d9704577 100644 --- a/libsrc/geom2d/geometry2d.hpp +++ b/libsrc/geom2d/geometry2d.hpp @@ -21,7 +21,7 @@ namespace netgen class SplineSegExt : public SplineSeg<2> { public: - const SplineSeg<2> & seg; + SplineSeg<2>* seg; /// left domain int leftdom; @@ -42,35 +42,43 @@ namespace netgen /// int layer; - SplineSegExt (const SplineSeg<2> & hseg) - : seg(hseg) + SplineSegExt (SplineSeg<2> & hseg) + : seg(&hseg) { layer = 1; } + // default constructor for archive + SplineSegExt() {} ~SplineSegExt () { - delete &seg; + delete seg; + } + + virtual void DoArchive(Archive& ar) + { + ar & seg & leftdom & rightdom & reffak & hmax & bc & copyfrom + & hpref_left & hpref_right & layer; } virtual const GeomPoint<2> & StartPI () const { - return seg.StartPI(); + return seg->StartPI(); } virtual const GeomPoint<2> & EndPI () const { - return seg.EndPI(); + return seg->EndPI(); } virtual Point<2> GetPoint (double t) const { - return seg.GetPoint(t); + return seg->GetPoint(t); } virtual Vec<2> GetTangent (const double t) const { - return seg.GetTangent(t); + return seg->GetTangent(t); } virtual void GetDerivatives (const double t, @@ -78,27 +86,27 @@ namespace netgen Vec<2> & first, Vec<2> & second) const { - seg.GetDerivatives (t, point, first, second); + seg->GetDerivatives (t, point, first, second); } virtual void GetCoeff (Vector & coeffs) const { - seg.GetCoeff (coeffs); + seg->GetCoeff (coeffs); } virtual void GetPoints (int n, Array > & points) const { - seg.GetPoints (n, points); + seg->GetPoints (n, points); } virtual double MaxCurvature () const { - return seg.MaxCurvature(); + return seg->MaxCurvature(); } virtual string GetType () const { - return seg.GetType(); + return seg->GetType(); } virtual double CalcCurvature (double t) const @@ -112,7 +120,7 @@ namespace netgen virtual bool InConvexHull (Point<2> p, double eps) const { - return seg.InConvexHull (p, eps); + return seg->InConvexHull (p, eps); } }; diff --git a/libsrc/gprim/spline.cpp b/libsrc/gprim/spline.cpp index 5b4afc33..2d888f9e 100644 --- a/libsrc/gprim/spline.cpp +++ b/libsrc/gprim/spline.cpp @@ -551,11 +551,10 @@ namespace netgen template class SplineSeg3<2>; template class SplineSeg3<3>; - - - - - - - + RegisterClassForArchive> regss2; + RegisterClassForArchive> regss3; + RegisterClassForArchive, SplineSeg<2>> regls2; + RegisterClassForArchive, SplineSeg<3>> regls3; + RegisterClassForArchive, SplineSeg<2>> regsss2; + RegisterClassForArchive, SplineSeg<3>> regsss3; } diff --git a/libsrc/gprim/spline.hpp b/libsrc/gprim/spline.hpp index a628d07d..1454d685 100644 --- a/libsrc/gprim/spline.hpp +++ b/libsrc/gprim/spline.hpp @@ -35,6 +35,11 @@ namespace netgen /// GeomPoint (const Point & ap, double aref = 1, double ahpref=0) : Point(ap), refatpoint(aref), hmax(1e99), hpref(ahpref) { ; } + void DoArchive(Archive& ar) + { + Point::DoArchive(ar); + ar & refatpoint & hmax & hpref; + } }; @@ -72,6 +77,7 @@ namespace netgen second = 1.0/sqr(eps) * ( (pr-point)+(pl-point)); } + virtual void DoArchive(Archive& ar) = 0; /// returns initial point on curve virtual const GeomPoint & StartPI () const = 0; @@ -122,6 +128,12 @@ namespace netgen /// LineSeg (const GeomPoint & ap1, const GeomPoint & ap2); /// + // default constructor for archive + LineSeg() {} + virtual void DoArchive(Archive& ar) + { + ar & p1 & p2; + } virtual double Length () const; /// inline virtual Point GetPoint (double t) const; @@ -172,7 +184,13 @@ namespace netgen SplineSeg3 (const GeomPoint & ap1, const GeomPoint & ap2, const GeomPoint & ap3); + // default constructor for archive + SplineSeg3() {} /// + virtual void DoArchive(Archive& ar) + { + ar & p1 & p2 & p3 & weight & proj_latest_t; + } inline virtual Point GetPoint (double t) const; /// virtual Vec GetTangent (const double t) const; @@ -226,6 +244,12 @@ namespace netgen CircleSeg (const GeomPoint & ap1, const GeomPoint & ap2, const GeomPoint & ap3); + // default constructor for archive + CircleSeg() {} + virtual void DoArchive(Archive& ar) + { + ar & p1 & p2 & p3 & pm & radius & w1 & w3; + } /// virtual Point GetPoint (double t) const; /// @@ -270,6 +294,12 @@ namespace netgen public: /// DiscretePointsSeg (const Array > & apts); + // default constructor for archive + DiscretePointsSeg() {} + virtual void DoArchive(Archive& ar) + { + ar & pts & p1n & p2n; + } /// virtual ~DiscretePointsSeg (); /// @@ -624,8 +654,14 @@ namespace netgen /// BSplineSeg (const Array > & apts); /// + //default constructor for archive + BSplineSeg() {} virtual ~BSplineSeg(); /// + virtual void DoArchive(Archive& ar) + { + ar & pts & p1n & p2n & ti; + } virtual Point GetPoint (double t) const; /// virtual const GeomPoint & StartPI () const { return p1n; }; diff --git a/libsrc/gprim/splinegeometry.hpp b/libsrc/gprim/splinegeometry.hpp index 16574516..8e01cc62 100644 --- a/libsrc/gprim/splinegeometry.hpp +++ b/libsrc/gprim/splinegeometry.hpp @@ -55,6 +55,10 @@ namespace netgen // void SetGrading (const double grading); DLL_HEADER void AppendPoint (const Point & p, const double reffac = 1., const bool hpref = false); + void DoArchive(Archive& ar) + { + ar & geompoints & splines; + } void AppendSegment(SplineSeg * spline) { diff --git a/libsrc/linalg/vector.hpp b/libsrc/linalg/vector.hpp index dec8b57d..97ad05ed 100644 --- a/libsrc/linalg/vector.hpp +++ b/libsrc/linalg/vector.hpp @@ -139,6 +139,14 @@ public: ~Vector () { if (ownmem) delete [] data; } + virtual void DoArchive(Archive& ar) + { + auto size = s; + ar & ownmem & size; + if(!ar.Output()) + SetSize(size); + ar.Do(data, size); + } Vector & operator= (const FlatVector & v) { memcpy (data, &v(0), s*sizeof(double)); return *this; } diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index f6fb4bc8..f5d38eb2 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -68,6 +68,21 @@ public: class NotRegisteredForArchive : public SharedPtrAndPtrHolder {}; +class ClassWithConstPtr +{ +private: + const int* ptr; +public: + ClassWithConstPtr(const int* aptr) : ptr(aptr) { } + // constructor only for archive + ClassWithConstPtr() {} + void DoArchive(Archive& ar) + { + ar & ptr; + } + const int* getPtr() { return ptr; } +}; + class OneMoreDerivedClass : public SharedPtrAndPtrHolder {}; static RegisterClassForArchive regb; @@ -110,18 +125,36 @@ void testSharedPointer(Archive& in, Archive& out) void testPointer(Archive& in, Archive& out) { - SECTION("Same pointer") + PtrHolder holder, holder2; + holder.numbers.push_back(new int(3)); + holder2.numbers = holder.numbers; // same shared ptr + out & holder & holder2; + out.FlushBuffer(); + PtrHolder inholder, inholder2; + in & inholder & inholder2; + CHECK(inholder.numbers.size() == 1); + CHECK(inholder.numbers[0] == inholder2.numbers[0]); + CHECK(*inholder.numbers[0] == 3); +} + +void testConstPointer(Archive& in, Archive& out) +{ + SECTION("Const pointer") { - PtrHolder holder, holder2; - holder.numbers.push_back(new int(3)); - holder2.numbers = holder.numbers; // same shared ptr - out & holder & holder2; + int* iptr = new int(4); + double d = 0.1; + ClassWithConstPtr cls(iptr); + out & cls & iptr & d; out.FlushBuffer(); - PtrHolder inholder, inholder2; - in & inholder & inholder2; - CHECK(inholder.numbers.size() == 1); - CHECK(inholder.numbers[0] == inholder2.numbers[0]); - CHECK(*inholder.numbers[0] == 3); + ClassWithConstPtr incls; + int* iniptr; + double ind; + in & incls & iniptr & ind; + CHECK(*incls.getPtr() == 4); + CHECK(incls.getPtr() == iniptr); + CHECK(ind == 0.1); + delete iptr; + delete iniptr; } } @@ -205,7 +238,7 @@ void testMultipleInheritance(Archive& in, Archive& out) void testLibraryVersion(Archive& in, Archive& out) { - GetLibraryVersions()["netgen"] = "v6.2.1812"; + SetLibraryVersion("netgen","v6.2.1812"); CHECK(in.getVersion("netgen") == "v6.2.1811"); CHECK(out.getVersion("netgen") == "v6.2.1812"); } @@ -214,12 +247,25 @@ void testArchive(Archive& in, Archive& out) { SECTION("Empty String") { - out << string("") << 1; + char* cstr = nullptr; + char* empty = new char[1]; + char* simple = new char[7] {'s','i','m','p','l','e','\0'}; + empty[0] = '\0'; + out << string("") << cstr << empty << simple << string("simple") << long(1); out.FlushBuffer(); - string str; int i; - in & str & i; + string str; long i; char* readempty; char* readsimple; + string simplestr; + in & str & cstr & readempty & readsimple & simplestr & i; CHECK(str == ""); + CHECK(cstr == nullptr); + CHECK(strcmp(readempty,"") == 0); + CHECK(strcmp(readsimple,"simple") == 0); CHECK(i == 1); + CHECK(simplestr == "simple"); + delete[] readempty; + delete[] empty; + delete[] simple; + delete[] readsimple; } SECTION("SharedPtr") { @@ -229,6 +275,10 @@ void testArchive(Archive& in, Archive& out) { testPointer(in, out); } + SECTION("Const Pointer") + { + testConstPointer(in, out); + } SECTION("Multiple inheritance") { testMultipleInheritance(in, out); @@ -250,7 +300,7 @@ void testArchive(Archive& in, Archive& out) TEST_CASE("BinaryArchive") { - GetLibraryVersions()["netgen"] = "v6.2.1811"; + SetLibraryVersion("netgen","v6.2.1811"); auto stream = make_shared(); BinaryOutArchive out(stream); BinaryInArchive in(stream); @@ -259,7 +309,7 @@ TEST_CASE("BinaryArchive") TEST_CASE("TextArchive") { - GetLibraryVersions()["netgen"] = "v6.2.1811"; + SetLibraryVersion("netgen","v6.2.1811"); auto stream = make_shared(); TextOutArchive out(stream); TextInArchive in(stream); diff --git a/tests/pytest/test_pickling.py b/tests/pytest/test_pickling.py new file mode 100644 index 00000000..7bbf1fa6 --- /dev/null +++ b/tests/pytest/test_pickling.py @@ -0,0 +1,40 @@ + +import netgen.csg as csg +import pickle, numpy +from ngsolve import Draw, Mesh + +def test_pickle_csg(): + geo = csg.CSGeometry() + geo.Add(csg.Sphere(csg.Pnt(0,0,0), 2).bc("sphere")) + brick = csg.OrthoBrick(csg.Pnt(-3,-3,-3), csg.Pnt(3,3,3)) + geo.Add(csg.Cylinder(csg.Pnt(0,0,0), csg.Pnt(1,0,0), 0.5) * brick) + geo.Add(csg.Ellipsoid(csg.Pnt(0,0,0), csg.Vec(1,0,0), csg.Vec(0,1,0), csg.Vec(0,0,0.5))) + geo.Add(csg.Cone(csg.Pnt(0,0,0), csg.Pnt(3,0,0), 1, 0.5) * brick) + geo.Add(csg.EllipticCone(csg.Pnt(0,0,0), csg.Vec(2,0,0), csg.Vec(0,1,0), 3, 0.5) * brick) + geo.Add(csg.Torus(csg.Pnt(0,0,0), csg.Vec(0,1,0), 0.3, 0.05)) + pts2d = [[1,1], [1,-1], [-1,-1], [-1,1]] + segs = [[0,1], [1,2], [2,3], [3,0]] + curve = csg.SplineCurve2d() + pnrs = [curve.AddPoint(*p) for p in pts2d] + for s in segs: + curve.AddSegment(pnrs[s[0]], pnrs[s[1]]) + geo.Add(csg.Revolution(csg.Pnt(0,0,0), csg.Pnt(1,0,0), curve)) + path = csg.SplineCurve3d() + pnts = [(0,0,0), (2,0,0), (2,2,0)] + segs = [(0,1,2)] + for pnt in pnts: + path.AddPoint (*pnt) + + for seg in segs: + path.AddSegment (*seg) + geo.Add(csg.Extrusion(path, curve, csg.Vec(0,0,1))) + + geo_dump = pickle.dumps(geo) + geo2 = pickle.loads(geo_dump) + vd1 = geo._visualizationData() + vd2 = geo2._visualizationData() + for val1, val2 in zip(vd1.values(), vd2.values()): + assert numpy.array_equal(val1, val2) + +if __name__ == "__main__": + test_pickle_csg() From 3bb82dd2dfc7895f5447c8d46232a6d13c6ecb17 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 7 Dec 2018 11:20:47 +0100 Subject: [PATCH 16/46] DoArchive for array only if T is archivable, little cleanup --- libsrc/core/basearchive.cpp | 17 +++- libsrc/core/basearchive.hpp | 150 +++++++++++++++++++++--------------- libsrc/core/ngcore.hpp | 1 - libsrc/core/type_traits.hpp | 4 +- libsrc/general/array.hpp | 4 +- libsrc/gprim/spline.cpp | 2 +- libsrc/gprim/spline.hpp | 2 +- 7 files changed, 107 insertions(+), 73 deletions(-) diff --git a/libsrc/core/basearchive.cpp b/libsrc/core/basearchive.cpp index 30f493bb..ad0d1866 100644 --- a/libsrc/core/basearchive.cpp +++ b/libsrc/core/basearchive.cpp @@ -25,9 +25,20 @@ namespace ngcore std::string demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, 0, 0, &status); } #endif - std::map& GetArchiveRegister() + static std::map* type_register; + const ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname) { - static std::map type_register; - return type_register; + if(!type_register) type_register = new std::map(); + return (*type_register)[classname]; + } + void Archive :: SetArchiveRegister(const std::string& classname, ClassArchiveInfo info) + { + if(!type_register) type_register = new std::map(); + (*type_register)[classname] = info; + } + bool Archive :: IsRegistered(const std::string& classname) + { + if(!type_register) type_register = new std::map(); + return type_register->count(classname) != 0; } } diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index 249c6e22..29cafd7b 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -22,7 +22,7 @@ namespace ngcore template T* constructIfPossible() { return constructIfPossible_impl(int{}); } - // Type trait to check if a class implements a 'void DoArchive(Archive&)' function + //Type trait to check if a class implements a 'void DoArchive(Archive&)' function template struct has_DoArchive { @@ -37,8 +37,21 @@ namespace ngcore static constexpr bool value = type::value; }; - // Info stored by registering a class using the RegisterClassForArchive struct in the map - // stored in GetArchiveRegister + // Check if class is archivable + template + struct is_Archivable + { + private: + template + static constexpr auto check(T2*) -> + typename std::is_same() & std::declval()),Archive&>::type; + template + static constexpr std::false_type check(...); + typedef decltype(check(nullptr)) type; + public: + static constexpr bool value = type::value; + }; + struct ClassArchiveInfo { // create new object of this type and return a void* pointer that is points to the location @@ -52,17 +65,6 @@ namespace ngcore std::function downcaster; }; - // Returns a map of from the mangled typeids to the ClassArchiveInfo - std::map& GetArchiveRegister(); - - // Helper class for up-/downcasting - template - struct Caster - { - static void* tryUpcast(const std::type_info& ti, T* p); - static void* tryDowncast(const std::type_info& ti, void* p); - }; - // Base Archive class class Archive { @@ -74,6 +76,23 @@ namespace ngcore // vectors for storing the unarchived (shared) pointers std::vector> nr2shared_ptr; std::vector nr2ptr; + + // Helper class for up-/downcasting + template + struct Caster + { + static void* tryUpcast(const std::type_info& ti, T* p); + static void* tryDowncast(const std::type_info& ti, void* p); + }; + template + friend class RegisterClassForArchive; + + // Returns ClassArchiveInfo of demangled typeid + static const ClassArchiveInfo& GetArchiveRegister(const std::string& classname); + // Set ClassArchiveInfo for demangled typeid, this is done by creating an instance of + // RegisterClassForArchive + static void SetArchiveRegister(const std::string& classname, ClassArchiveInfo info); + static bool IsRegistered(const std::string& classname); public: Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; } virtual ~Archive() { ; } @@ -147,7 +166,7 @@ namespace ngcore } // Archive arrays ===================================================== // this functions can be overloaded in Archive implementations for more efficiency - template + template ::value>::type> Archive & Do (T * data, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; @@ -194,11 +213,11 @@ namespace ngcore // Downcasting is only possible for our registered classes if(typeid(T) != typeid(*ptr)) { - if(GetArchiveRegister().count(demangle(typeid(*ptr).name())) == 0) + if(!IsRegistered(demangle(typeid(*ptr).name()))) throw std::runtime_error(std::string("Archive error: Polymorphic type ") + demangle(typeid(*ptr).name()) + " not registered for archive"); - reg_ptr = GetArchiveRegister()[demangle(typeid(*ptr).name())].downcaster(typeid(T), ptr.get()); + reg_ptr = GetArchiveRegister(demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); // if there was a true downcast we have to store more information if(reg_ptr != (void*) ptr.get()) neededDowncast = true; @@ -244,7 +263,7 @@ namespace ngcore { std::string name; (*this) & name; - auto info = GetArchiveRegister()[name]; + auto info = GetArchiveRegister(name); // for this we use an aliasing constructor to create a shared pointer sharing lifetime // with our shared ptr, but pointing to the true object nr2shared_ptr.push_back(std::shared_ptr(std::static_pointer_cast(ptr), @@ -265,7 +284,7 @@ namespace ngcore // wouldn't have worked else) std::string name; (*this) & name; - auto info = GetArchiveRegister()[name]; + auto info = GetArchiveRegister(name); // same trick as above, create a shared ptr sharing lifetime with // the shared_ptr in the register, but pointing to our object ptr = std::static_pointer_cast(std::shared_ptr(other, @@ -291,12 +310,12 @@ namespace ngcore void* reg_ptr = (void*)p; if(typeid(T) != typeid(*p)) { - if(GetArchiveRegister().count(demangle(typeid(*p).name())) == 0) + if(!IsRegistered(demangle(typeid(*p).name()))) throw std::runtime_error(std::string("Archive error: Polymorphic type ") + demangle(typeid(*p).name()) + " not registered for archive"); else - reg_ptr = GetArchiveRegister()[demangle(typeid(*p).name())].downcaster(typeid(T), (void*) p); + reg_ptr = GetArchiveRegister(demangle(typeid(*p).name())).downcaster(typeid(T), (void*) p); } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry @@ -317,7 +336,7 @@ namespace ngcore // to avoid compile time issues we allow this behaviour only for "our" classes that // implement a void DoArchive(Archive&) member function // To recreate the object we need to store the true type of it - if(GetArchiveRegister().count(demangle(typeid(*p).name())) == 0) + if(!IsRegistered(demangle(typeid(*p).name()))) throw std::runtime_error(std::string("Archive error: Polymorphic type ") + demangle(typeid(*p).name()) + " not registered for archive"); @@ -350,7 +369,7 @@ namespace ngcore // As stated above, we want this special behaviour only for our classes that implement DoArchive std::string name; (*this) & name; - auto info = GetArchiveRegister()[name]; + auto info = GetArchiveRegister(name); // the creator creates a new object of type name, and returns a void* pointing // to T (which may have an offset) p = (T*) info.creator(typeid(T)); @@ -366,9 +385,9 @@ namespace ngcore (*this) & downcasted & name; if(downcasted) { - // if the class has been downcasted we can assume it is in the register - auto info = GetArchiveRegister()[name]; - p = (T*) info.upcaster(typeid(T), nr2ptr[nr]); + // if the class has been downcasted we can assume it is in the register + auto info = GetArchiveRegister(name); + p = (T*) info.upcaster(typeid(T), nr2ptr[nr]); } else p = (T*) nr2ptr[nr]; @@ -397,6 +416,41 @@ namespace ngcore protected: static std::map& GetLibraryVersions(); + private: + template + struct Caster + { + static void* tryUpcast (const std::type_info& ti, T* p) + { + throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!"); + } + static void* tryDowncast (const std::type_info& ti, void* p) + { + throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!"); + } + }; + + template + struct Caster + { + static void* tryUpcast(const std::type_info& ti, T* p) + { + try + { return GetArchiveRegister(demangle(typeid(B1).name())).upcaster(ti, (void*) (dynamic_cast(p))); } + catch(std::exception) + { return Caster::tryUpcast(ti, p); } + } + + static void* tryDowncast(const std::type_info& ti, void* p) + { + if(typeid(B1) == ti) + return dynamic_cast((B1*) p); + try + { return GetArchiveRegister(demangle(typeid(B1).name())).downcaster(ti, (void*) ((B1*)p)); } + catch(std::exception) + { return Caster::tryDowncast(ti, p); } + } + }; }; template @@ -410,49 +464,17 @@ namespace ngcore ClassArchiveInfo info; info.creator = [this,&info](const std::type_info& ti) -> void* { return typeid(T) == ti ? constructIfPossible() - : Caster::tryUpcast(ti, constructIfPossible()); }; + : Archive::Caster::tryUpcast(ti, constructIfPossible()); }; info.upcaster = [this](const std::type_info& ti, void* p) -> void* - { return typeid(T) == ti ? p : Caster::tryUpcast(ti, (T*) p); }; + { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, (T*) p); }; info.downcaster = [this](const std::type_info& ti, void* p) -> void* - { return typeid(T) == ti ? p : Caster::tryDowncast(ti, p); }; - GetArchiveRegister()[std::string(demangle(typeid(T).name()))] = info; - } - }; - - template - struct Caster - { - static void* tryUpcast (const std::type_info& ti, T* p) - { - throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!"); - } - static void* tryDowncast (const std::type_info& ti, void* p) - { - throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!"); - } - }; - - template - struct Caster - { - static void* tryUpcast(const std::type_info& ti, T* p) - { - try - { return GetArchiveRegister()[demangle(typeid(B1).name())].upcaster(ti, (void*) (dynamic_cast(p))); } - catch(std::exception) - { return Caster::tryUpcast(ti, p); } + { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; + Archive::SetArchiveRegister(std::string(demangle(typeid(T).name())),info); } - static void* tryDowncast(const std::type_info& ti, void* p) - { - if(typeid(B1) == ti) - return dynamic_cast((B1*) p); - try - { return GetArchiveRegister()[demangle(typeid(B1).name())].downcaster(ti, (void*) ((B1*)p)); } - catch(std::exception) - { return Caster::tryDowncast(ti, p); } - } + }; + } #endif // NG_BASEARCHIVE_HPP diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index 9d600991..5c3b5338 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -15,7 +15,6 @@ #include #include - namespace ngcore { #if defined(__GNUC__) diff --git a/libsrc/core/type_traits.hpp b/libsrc/core/type_traits.hpp index 3d515c08..b77a612e 100644 --- a/libsrc/core/type_traits.hpp +++ b/libsrc/core/type_traits.hpp @@ -3,6 +3,6 @@ namespace ngcore { template struct _BoolArray{}; - template - constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(T || true)...>>::value; + template + constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(vals || true)...>>::value; } diff --git a/libsrc/general/array.hpp b/libsrc/general/array.hpp index 8f8263e8..bd2b569a 100644 --- a/libsrc/general/array.hpp +++ b/libsrc/general/array.hpp @@ -401,7 +401,9 @@ namespace netgen return data; } - void DoArchive(Archive& archive) + // Only provide this function if T is archivable + template + auto DoArchive(Archive& archive) -> typename std::enable_if::value, void>::type { if(archive.Output()) archive << size; diff --git a/libsrc/gprim/spline.cpp b/libsrc/gprim/spline.cpp index 2d888f9e..3f8ccf98 100644 --- a/libsrc/gprim/spline.cpp +++ b/libsrc/gprim/spline.cpp @@ -99,7 +99,7 @@ namespace netgen } template - inline Point SplineSeg3 :: GetPoint (double t) const + Point SplineSeg3 :: GetPoint (double t) const { double b1, b2, b3; diff --git a/libsrc/gprim/spline.hpp b/libsrc/gprim/spline.hpp index 1454d685..90935d42 100644 --- a/libsrc/gprim/spline.hpp +++ b/libsrc/gprim/spline.hpp @@ -191,7 +191,7 @@ namespace netgen { ar & p1 & p2 & p3 & weight & proj_latest_t; } - inline virtual Point GetPoint (double t) const; + virtual Point GetPoint (double t) const; /// virtual Vec GetTangent (const double t) const; From b064b9bbfdc14fc08d871b42c5d5f6c464fd0b2b Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 7 Dec 2018 11:39:00 +0100 Subject: [PATCH 17/46] dll header --- libsrc/core/archive.hpp | 8 ++++---- libsrc/core/basearchive.hpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 4a25748c..425b4c7b 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -4,7 +4,7 @@ namespace ngcore { // BinaryOutArchive ====================================================================== - class BinaryOutArchive : public Archive + class DLL_HEADER BinaryOutArchive : public Archive { size_t ptr = 0; enum { BUFFERSIZE = 1024 }; @@ -82,7 +82,7 @@ namespace ngcore }; // BinaryInArchive ====================================================================== - class BinaryInArchive : public Archive + class DLL_HEADER BinaryInArchive : public Archive { std::map vinfo; std::shared_ptr fin; @@ -150,7 +150,7 @@ namespace ngcore }; // TextOutArchive ====================================================================== - class TextOutArchive : public Archive + class DLL_HEADER TextOutArchive : public Archive { std::shared_ptr fout; public: @@ -204,7 +204,7 @@ namespace ngcore }; // TextInArchive ====================================================================== - class TextInArchive : public Archive + class DLL_HEADER TextInArchive : public Archive { std::map vinfo; std::shared_ptr fin; diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index 29cafd7b..9bd15be0 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -9,7 +9,7 @@ namespace ngcore void SetLibraryVersion(const std::string& library, VersionInfo version); class Archive; - std::string demangle(const char* typeinfo); + DLL_HEADER std::string demangle(const char* typeinfo); // create new pointer of type T if it is default constructible, else throw template @@ -34,7 +34,7 @@ namespace ngcore static constexpr std::false_type check(...); typedef decltype(check(0)) type; public: - static constexpr bool value = type::value; + DLL_HEADER static constexpr bool value = type::value; }; // Check if class is archivable @@ -49,7 +49,7 @@ namespace ngcore static constexpr std::false_type check(...); typedef decltype(check(nullptr)) type; public: - static constexpr bool value = type::value; + DLL_HEADER static constexpr bool value = type::value; }; struct ClassArchiveInfo @@ -66,7 +66,7 @@ namespace ngcore }; // Base Archive class - class Archive + class DLL_HEADER Archive { bool is_output; // how many different shared_ptr/pointer have been (un)archived @@ -454,7 +454,7 @@ namespace ngcore }; template - class RegisterClassForArchive + class DLL_HEADER RegisterClassForArchive { public: RegisterClassForArchive() From 32bc3f826e8b8e773bfec8dd76e477aded372bc8 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 7 Dec 2018 11:41:56 +0100 Subject: [PATCH 18/46] once only header for hpp files --- libsrc/core/type_traits.hpp | 5 ++++- libsrc/core/version.hpp | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libsrc/core/type_traits.hpp b/libsrc/core/type_traits.hpp index b77a612e..894a5d07 100644 --- a/libsrc/core/type_traits.hpp +++ b/libsrc/core/type_traits.hpp @@ -1,4 +1,5 @@ - +#ifndef NGS_TYPE_TRAITS_HPP +#define NGS_TYPE_TRAITS_HPP namespace ngcore { @@ -6,3 +7,5 @@ namespace ngcore template constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(vals || true)...>>::value; } + +#endif // NGS_TYPE_TRAITS_HPP diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp index 81932695..152dbe1a 100644 --- a/libsrc/core/version.hpp +++ b/libsrc/core/version.hpp @@ -1,3 +1,5 @@ +#ifndef NGS_VERSION_HPP +#define NGS_VERSION_HPP namespace ngcore { @@ -82,3 +84,4 @@ namespace ngcore } }; } +#endif // NGS_VERSION_HPP From 69769fc6286f673ab70ca5df9a64e943f317e14b Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 7 Dec 2018 11:45:39 +0100 Subject: [PATCH 19/46] mayor and minor are macros defined in GNU_SOURCE... --- libsrc/core/version.hpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp index 152dbe1a..f73aad23 100644 --- a/libsrc/core/version.hpp +++ b/libsrc/core/version.hpp @@ -6,24 +6,24 @@ namespace ngcore class VersionInfo { private: - size_t mayor, minor, release, patch; + size_t mayor_, minor_, release, patch; std::string git_hash; public: - VersionInfo() : mayor(0), minor(0), release(0), patch(0), git_hash("") {} + VersionInfo() : mayor_(0), minor_(0), release(0), patch(0), git_hash("") {} VersionInfo(std::string vstring) { - minor = release = patch = 0; + minor_ = release = patch = 0; git_hash = ""; if(vstring.substr(0,1) == "v") vstring = vstring.substr(1,vstring.size()-1); auto dot = vstring.find("."); - mayor = std::stoi(vstring.substr(0,dot)); + mayor_ = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1, vstring.size()-dot-1); if(vstring.size()) { dot = vstring.find("."); - minor = std::stoi(vstring.substr(0,dot)); + minor_ = std::stoi(vstring.substr(0,dot)); if (dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1, vstring.size()-dot-1); if(vstring.size()) @@ -47,10 +47,10 @@ namespace ngcore VersionInfo(const char* cstr) : VersionInfo(std::string(cstr)) { } std::string to_string() const - { std::string vstring = "v" + std::to_string(mayor); - if(minor || release || patch || git_hash.size()) + { std::string vstring = "v" + std::to_string(mayor_); + if(minor_ || release || patch || git_hash.size()) { - vstring += "." + std::to_string(minor); + vstring += "." + std::to_string(minor_); if(release || patch || git_hash.size()) { vstring += "." + std::to_string(release); @@ -66,12 +66,12 @@ namespace ngcore } bool operator <(const VersionInfo& other) const { - return std::tie(mayor, minor, release, patch) < - std::tie(other.mayor, other.minor, other.release, other.patch); + return std::tie(mayor_, minor_, release, patch) < + std::tie(other.mayor_, other.minor_, other.release, other.patch); } bool operator ==(const VersionInfo& other) const { - return mayor == other.mayor && minor == other.minor && release == other.release + return mayor_ == other.mayor_ && minor_ == other.minor_ && release == other.release && patch == other.patch; } bool operator >(const VersionInfo& other) const { return other < (*this); } @@ -80,7 +80,7 @@ namespace ngcore void DoArchive(Archive& ar) { - ar & mayor & minor & release & patch & git_hash; + ar & mayor_ & minor_ & release & patch & git_hash; } }; } From 0dc04b661c753df049f63513a64f1acfedff95e9 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Fri, 7 Dec 2018 13:08:00 +0100 Subject: [PATCH 20/46] [ngcore] DLL exports --- libsrc/core/CMakeLists.txt | 2 +- libsrc/core/archive.hpp | 8 ++++---- libsrc/core/basearchive.hpp | 10 +++++----- libsrc/core/ngcore.hpp | 14 ++++++++++++++ 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 04efdf01..ef983cc9 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,7 +1,7 @@ -add_definitions(-DNGINTERFACE_EXPORTS) add_library(ngcore basearchive.cpp) set_target_properties(ngcore PROPERTIES POSITION_INDEPENDENT_CODE ON ) +target_compile_definitions(ngcore PRIVATE -DNGCORE_EXPORTS) install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 425b4c7b..bbacab8d 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -4,7 +4,7 @@ namespace ngcore { // BinaryOutArchive ====================================================================== - class DLL_HEADER BinaryOutArchive : public Archive + class NGCORE_API BinaryOutArchive : public Archive { size_t ptr = 0; enum { BUFFERSIZE = 1024 }; @@ -82,7 +82,7 @@ namespace ngcore }; // BinaryInArchive ====================================================================== - class DLL_HEADER BinaryInArchive : public Archive + class NGCORE_API BinaryInArchive : public Archive { std::map vinfo; std::shared_ptr fin; @@ -150,7 +150,7 @@ namespace ngcore }; // TextOutArchive ====================================================================== - class DLL_HEADER TextOutArchive : public Archive + class NGCORE_API TextOutArchive : public Archive { std::shared_ptr fout; public: @@ -204,7 +204,7 @@ namespace ngcore }; // TextInArchive ====================================================================== - class DLL_HEADER TextInArchive : public Archive + class NGCORE_API TextInArchive : public Archive { std::map vinfo; std::shared_ptr fin; diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index 9bd15be0..7e1f7335 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -9,7 +9,7 @@ namespace ngcore void SetLibraryVersion(const std::string& library, VersionInfo version); class Archive; - DLL_HEADER std::string demangle(const char* typeinfo); + NGCORE_API std::string demangle(const char* typeinfo); // create new pointer of type T if it is default constructible, else throw template @@ -34,7 +34,7 @@ namespace ngcore static constexpr std::false_type check(...); typedef decltype(check(0)) type; public: - DLL_HEADER static constexpr bool value = type::value; + NGCORE_API static constexpr bool value = type::value; }; // Check if class is archivable @@ -49,7 +49,7 @@ namespace ngcore static constexpr std::false_type check(...); typedef decltype(check(nullptr)) type; public: - DLL_HEADER static constexpr bool value = type::value; + NGCORE_API static constexpr bool value = type::value; }; struct ClassArchiveInfo @@ -66,7 +66,7 @@ namespace ngcore }; // Base Archive class - class DLL_HEADER Archive + class NGCORE_API Archive { bool is_output; // how many different shared_ptr/pointer have been (un)archived @@ -454,7 +454,7 @@ namespace ngcore }; template - class DLL_HEADER RegisterClassForArchive + class NGCORE_API RegisterClassForArchive { public: RegisterClassForArchive() diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index 5c3b5338..1c364730 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -15,6 +15,20 @@ #include #include +#ifdef WIN32 + #define NGCORE_API_EXPORT __declspec(dllexport) + #define NGCORE_API_IMPORT __declspec(dllimport) +#else + #define NGCORE_API_EXPORT + #define NGCORE_API_IMPORT +#endif + +#ifdef NGCORE_EXPORTS + #define NGCORE_API NGCORE_API_EXPORT +#else + #define NGCORE_API NGCORE_API_IMPORT +#endif + namespace ngcore { #if defined(__GNUC__) From 17aba88117bf99985b22c446746a896ca2c6c5e0 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Sat, 8 Dec 2018 16:10:29 +0100 Subject: [PATCH 21/46] [ngcore] follow cpp guidelines, check them with clang-tidy --- CMakeLists.txt | 15 ++ cmake/SuperBuild.cmake | 1 + libsrc/core/CMakeLists.txt | 12 +- libsrc/core/archive.cpp | 57 +++++ libsrc/core/archive.hpp | 496 +++++++++++++++++++++++++++++++++++- libsrc/core/basearchive.cpp | 44 ---- libsrc/core/basearchive.hpp | 480 ---------------------------------- libsrc/core/ngcore.hpp | 50 +--- libsrc/core/ngcore_api.hpp | 29 +++ libsrc/core/type_traits.hpp | 4 +- libsrc/core/version.cpp | 11 + libsrc/core/version.hpp | 19 +- tests/catch/CMakeLists.txt | 6 + 13 files changed, 636 insertions(+), 588 deletions(-) create mode 100644 libsrc/core/archive.cpp delete mode 100644 libsrc/core/basearchive.cpp delete mode 100644 libsrc/core/basearchive.hpp create mode 100644 libsrc/core/ngcore_api.hpp create mode 100644 libsrc/core/version.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c947e762..33d2d835 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ option( INSTALL_PROFILES "install environment variable settings to /etc/profile. option( USE_CCACHE "use ccache") option( USE_INTERNAL_TCL "Compile tcl files into the code and don't install them" ON) option( ENABLE_UNIT_TESTS "Enable Catch unit tests") +option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF) option( USE_SUPERBUILD "use ccache" ON) @@ -349,6 +350,20 @@ endif(ENABLE_UNIT_TESTS) ####################################################################### +if(ENABLE_CPP_CORE_GUIDELINES_CHECK) + find_program( + CLANG_TIDY_EXE + NAMES "clang-tidy" + DOC "Path to clang-tidy executable" + ) + if(NOT CLANG_TIDY_EXE) + message(WARNING "clang-tidy not found.") + else() + message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") + set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-checks=*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-default-arguments") + endif() +endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) + add_subdirectory(libsrc) add_subdirectory(ng) add_subdirectory(tutorials) diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index c5b3cb47..36ea3fcb 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -141,6 +141,7 @@ set_vars( NETGEN_CMAKE_ARGS CMAKE_PREFIX_PATH CMAKE_INSTALL_PREFIX ENABLE_UNIT_TESTS + ENABLE_CPP_CORE_GUIDELINES_CHECK ) # propagate all variables set on the command line using cmake -DFOO=BAR diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index ef983cc9..337bbfaa 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,10 +1,14 @@ -add_library(ngcore basearchive.cpp) + +add_library(ngcore archive.cpp version.cpp) set_target_properties(ngcore PROPERTIES POSITION_INDEPENDENT_CODE ON ) target_compile_definitions(ngcore PRIVATE -DNGCORE_EXPORTS) install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) -install(FILES ngcore.hpp archive.hpp basearchive.hpp version.hpp type_traits.hpp - DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel -) +install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp + DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) + +if(ENABLE_CPP_CORE_GUIDELINES_CHECK) + set_target_properties(ngcore PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") +endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/archive.cpp b/libsrc/core/archive.cpp new file mode 100644 index 00000000..9fe54704 --- /dev/null +++ b/libsrc/core/archive.cpp @@ -0,0 +1,57 @@ + +#include "archive.hpp" + +#ifndef WIN32 +#include +#endif + +namespace ngcore +{ + void VersionInfo :: DoArchive(Archive& ar) + { + ar & mayor_ & minor_ & release & patch & git_hash; + } + + // clang-tidy should ignore this static object + static std::map library_versions; // NOLINT + std::map& Archive :: GetLibraryVersions() + { + return library_versions; + } + const VersionInfo& GetLibraryVersion(const std::string& library) + { return library_versions[library]; } + + void SetLibraryVersion(const std::string& library, const VersionInfo& version) + { library_versions[library] = version; } + +#ifdef WIN + // windows does demangling in typeid(T).name() + std::string demangle(const char* typeinfo) { return typeinfo; } +#else + std::string demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, + nullptr, + nullptr, + &status); } +#endif + + // clang-tidy should ignore this static object + static std::unique_ptr> type_register; // NOLINT + const ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname) + { + if(type_register == nullptr) type_register = + std::make_unique>(); + return (*type_register)[classname]; + } + void Archive :: SetArchiveRegister(const std::string& classname, const ClassArchiveInfo& info) + { + if(type_register == nullptr) type_register = + std::make_unique>(); + (*type_register)[classname] = info; + } + bool Archive :: IsRegistered(const std::string& classname) + { + if(type_register == nullptr) type_register = + std::make_unique>(); + return type_register->count(classname) != 0; + } +} // namespace ngcore diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index bbacab8d..89656ad5 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -1,8 +1,493 @@ -#ifndef NG_ARCHIVE_HPP -#define NG_ARCHIVE_HPP +#ifndef NETGEN_CORE_ARCHIVE_HPP +#define NETGEN_CORE_ARCHIVE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ngcore_api.hpp" +#include "type_traits.hpp" +#include "version.hpp" namespace ngcore { + // Libraries using this archive can store their version here to implement backwards compatibility + const VersionInfo& GetLibraryVersion(const std::string& library); + void SetLibraryVersion(const std::string& library, const VersionInfo& version); + + class Archive; + NGCORE_API std::string demangle(const char* typeinfo); + + // create new pointer of type T if it is default constructible, else throw + template + T* constructIfPossible_impl(...) + { throw std::runtime_error(std::string(demangle(typeid(T).name())) + " is not default constructible!"); } + + template::value>::type> + T* constructIfPossible_impl(int) { return new T; } + + template + T* constructIfPossible() { return constructIfPossible_impl(int{}); } + + //Type trait to check if a class implements a 'void DoArchive(Archive&)' function + template + struct has_DoArchive + { + private: + template + static constexpr auto check(T2*) -> + typename std::is_same().DoArchive(std::declval())),void>::type; + template + static constexpr std::false_type check(...); + typedef decltype(check(0)) type; + public: + NGCORE_API static constexpr bool value = type::value; + }; + + // Check if class is archivable + template + struct is_Archivable + { + private: + template + static constexpr auto check(T2*) -> + typename std::is_same() & std::declval()),Archive&>::type; + template + static constexpr std::false_type check(...); + typedef decltype(check(nullptr)) type; + public: + NGCORE_API static constexpr bool value = type::value; + }; + + struct ClassArchiveInfo + { + // create new object of this type and return a void* pointer that is points to the location + // of the (base)class given by type_info + std::function creator; + // This caster takes a void* pointer to the type stored in this info and casts it to a + // void* pointer pointing to the (base)class type_info + std::function upcaster; + // This caster takes a void* pointer to the (base)class type_info and returns void* pointing + // to the type stored in this info + std::function downcaster; + }; + + // Base Archive class + class NGCORE_API Archive + { + bool is_output; + // how many different shared_ptr/pointer have been (un)archived + int shared_ptr_count, ptr_count; + // maps for archived shared pointers and pointers + std::map shared_ptr2nr, ptr2nr; + // vectors for storing the unarchived (shared) pointers + std::vector> nr2shared_ptr; + std::vector nr2ptr; + + // Helper class for up-/downcasting + template + struct Caster + { + static void* tryUpcast(const std::type_info& ti, T* p); + static void* tryDowncast(const std::type_info& ti, void* p); + }; + template + friend class RegisterClassForArchive; + + // Returns ClassArchiveInfo of demangled typeid + static const ClassArchiveInfo& GetArchiveRegister(const std::string& classname); + // Set ClassArchiveInfo for demangled typeid, this is done by creating an instance of + // RegisterClassForArchive + static void SetArchiveRegister(const std::string& classname, const ClassArchiveInfo& info); + static bool IsRegistered(const std::string& classname); + public: + Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; } + virtual ~Archive() { ; } + + bool Output () { return is_output; } + bool Input () { return !is_output; } + virtual const VersionInfo& getVersion(const std::string& library) = 0; + + // Pure virtual functions that have to be implemented by In-/OutArchive + virtual Archive & operator & (double & d) = 0; + virtual Archive & operator & (int & i) = 0; + virtual Archive & operator & (long & i) = 0; + virtual Archive & operator & (size_t & i) = 0; + virtual Archive & operator & (short & i) = 0; + virtual Archive & operator & (unsigned char & i) = 0; + virtual Archive & operator & (bool & b) = 0; + virtual Archive & operator & (std::string & str) = 0; + virtual Archive & operator & (char *& str) = 0; + + + // Archive std classes ================================================ + template + Archive& operator & (std::complex& c) + { + if(is_output) + (*this) << c.real() << c.imag(); + else + { + T tmp; + (*this) & tmp; + c.real(tmp); + (*this) & tmp; + c.imag(tmp); + } + return (*this); + } + template + Archive& operator & (std::vector& v) + { + size_t size; + if(is_output) + size = v.size(); + (*this) & size; + if(!is_output) + v.resize(size); + Do(&v[0], size); + return (*this); + } + template + Archive& operator& (std::map& map) + { + if(is_output) + { + (*this) << size_t(map.size()); + for(auto& pair : map) + (*this) << pair.first << pair.second; + } + else + { + size_t size; + (*this) & size; + T1 key; T2 val; + for(size_t i = 0; i < size; i++) + { + T1 key; T2 val; + (*this) & key & val; + map[key] = val; + } + } + return (*this); + } + // Archive arrays ===================================================== + // this functions can be overloaded in Archive implementations for more efficiency + template ::value>::type> + Archive & Do (T * data, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; + + virtual Archive & Do (double * d, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; + + virtual Archive & Do (int * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + + virtual Archive & Do (long * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + + virtual Archive & Do (size_t * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + + virtual Archive & Do (short * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + + virtual Archive & Do (unsigned char * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + + virtual Archive & Do (bool * b, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; + + // Archive a class implementing a (void DoArchive(Archive&)) method ======= + template::value>> + Archive& operator & (T& val) + { + val.DoArchive(*this); return *this; + } + + // Archive shared_ptrs ================================================= + template + Archive& operator & (std::shared_ptr& ptr) + { + if(Output()) + { + // save -2 for nullptr + if(!ptr) + return (*this) << -2; + + void* reg_ptr = ptr.get(); + bool neededDowncast = false; + // Downcasting is only possible for our registered classes + if(typeid(T) != typeid(*ptr)) + { + if(!IsRegistered(demangle(typeid(*ptr).name()))) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + + demangle(typeid(*ptr).name()) + + " not registered for archive"); + reg_ptr = GetArchiveRegister(demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); + // if there was a true downcast we have to store more information + if(reg_ptr != (void*) ptr.get()) + neededDowncast = true; + } + auto pos = shared_ptr2nr.find(reg_ptr); + // if not found store -1 and the pointer + if(pos == shared_ptr2nr.end()) + { + auto p = ptr.get(); + (*this) << -1; + (*this) & neededDowncast & p; + // if we did downcast we store the true type as well + if(neededDowncast) + (*this) << demangle(typeid(*ptr).name()); + shared_ptr2nr[reg_ptr] = shared_ptr_count++; + return *this; + } + // if found store the position and if it has to be downcasted and how + (*this) << pos->second << neededDowncast; + if(neededDowncast) + (*this) << demangle(typeid(*ptr).name()); + return (*this); + } + else // Input + { + int nr; + (*this) & nr; + // -2 restores a nullptr + if(nr == -2) + { + ptr = nullptr; + return *this; + } + // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it + else if (nr == -1) + { + T* p; + bool neededDowncast; + (*this) & neededDowncast & p; + ptr = std::shared_ptr(p); + // if we did downcast we need to store a shared_ptr to the true object + if(neededDowncast) + { + std::string name; + (*this) & name; + auto info = GetArchiveRegister(name); + // for this we use an aliasing constructor to create a shared pointer sharing lifetime + // with our shared ptr, but pointing to the true object + nr2shared_ptr.push_back(std::shared_ptr(std::static_pointer_cast(ptr), + info.downcaster(typeid(T), + ptr.get()))); + } + else + nr2shared_ptr.push_back(ptr); + } + else + { + auto other = nr2shared_ptr[nr]; + bool neededDowncast; + (*this) & neededDowncast; + if(neededDowncast) + { + // if there was a downcast we can expect the class to be registered (since archiving + // wouldn't have worked else) + std::string name; + (*this) & name; + auto info = GetArchiveRegister(name); + // same trick as above, create a shared ptr sharing lifetime with + // the shared_ptr in the register, but pointing to our object + ptr = std::static_pointer_cast(std::shared_ptr(other, + info.upcaster(typeid(T), + other.get()))); + } + else + ptr = std::static_pointer_cast(other); + } + } + return *this; + } + + // Archive pointers ======================================================= + template + Archive & operator& (T *& p) + { + if (Output()) + { + // if the pointer is null store -2 + if (!p) + return (*this) << -2; + void* reg_ptr = (void*)p; + if(typeid(T) != typeid(*p)) + { + if(!IsRegistered(demangle(typeid(*p).name()))) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + + demangle(typeid(*p).name()) + + " not registered for archive"); + else + reg_ptr = GetArchiveRegister(demangle(typeid(*p).name())).downcaster(typeid(T), (void*) p); + } + auto pos = ptr2nr.find(reg_ptr); + // if the pointer is not found in the map create a new entry + if (pos == ptr2nr.end()) + { + ptr2nr[reg_ptr] = ptr_count++; + if(typeid(*p) == typeid(T)) + if (std::is_constructible::value) + { + return (*this) << -1 & (*p); + } + else + throw std::runtime_error(std::string("Archive error: Class ") + + demangle(typeid(*p).name()) + " does not provide a default constructor!"); + else + { + // if a pointer to a base class is archived, the class hierarchy must be registered + // to avoid compile time issues we allow this behaviour only for "our" classes that + // implement a void DoArchive(Archive&) member function + // To recreate the object we need to store the true type of it + if(!IsRegistered(demangle(typeid(*p).name()))) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + + demangle(typeid(*p).name()) + + " not registered for archive"); + else + return (*this) << -3 << demangle(typeid(*p).name()) & (*p); + } + } + else + { + (*this) & pos->second; + bool downcasted = !(reg_ptr == (void*) p); + // store if the class has been downcasted and the name + (*this) << downcasted << demangle(typeid(*p).name()); + } + } + else + { + int nr; + (*this) & nr; + if (nr == -2) // restore a nullptr + p = nullptr; + else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) + { + p = constructIfPossible(); + nr2ptr.push_back(p); + (*this) & *p; + } + else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... + { + // As stated above, we want this special behaviour only for our classes that implement DoArchive + std::string name; + (*this) & name; + auto info = GetArchiveRegister(name); + // the creator creates a new object of type name, and returns a void* pointing + // to T (which may have an offset) + p = (T*) info.creator(typeid(T)); + // we store the downcasted pointer (to be able to find it again from + // another class in a multiple inheritance tree) + nr2ptr.push_back(info.downcaster(typeid(T),p)); + (*this) & *p; + } + else + { + bool downcasted; + std::string name; + (*this) & downcasted & name; + if(downcasted) + { + // if the class has been downcasted we can assume it is in the register + auto info = GetArchiveRegister(name); + p = (T*) info.upcaster(typeid(T), nr2ptr[nr]); + } + else + p = (T*) nr2ptr[nr]; + } + } + return *this; + } + + // const ptr + template + Archive& operator &(const T*& t) + { + return (*this) & const_cast(t); + } + + // Write a read only variable + template + Archive & operator << (const T & t) + { + T ht(t); + (*this) & ht; + return *this; + } + + virtual void FlushBuffer() {} + + protected: + static std::map& GetLibraryVersions(); + private: + template + struct Caster + { + static void* tryUpcast (const std::type_info& ti, T* p) + { + throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!"); + } + static void* tryDowncast (const std::type_info& ti, void* p) + { + throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!"); + } + }; + + template + struct Caster + { + static void* tryUpcast(const std::type_info& ti, T* p) + { + try + { return GetArchiveRegister(demangle(typeid(B1).name())).upcaster(ti, (void*) (dynamic_cast(p))); } + catch(std::exception) + { return Caster::tryUpcast(ti, p); } + } + + static void* tryDowncast(const std::type_info& ti, void* p) + { + if(typeid(B1) == ti) + return dynamic_cast((B1*) p); + try + { return GetArchiveRegister(demangle(typeid(B1).name())).downcaster(ti, (void*) ((B1*)p)); } + catch(std::exception) + { return Caster::tryDowncast(ti, p); } + } + }; + }; + + template + class NGCORE_API RegisterClassForArchive + { + public: + RegisterClassForArchive() + { + static_assert(all_of_tmpl::value...>, + "Variadic template arguments must be base classes of T"); + ClassArchiveInfo info; + info.creator = [this,&info](const std::type_info& ti) -> void* + { return typeid(T) == ti ? constructIfPossible() + : Archive::Caster::tryUpcast(ti, constructIfPossible()); }; + info.upcaster = [this](const std::type_info& ti, void* p) -> void* + { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, (T*) p); }; + info.downcaster = [this](const std::type_info& ti, void* p) -> void* + { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; + Archive::SetArchiveRegister(std::string(demangle(typeid(T).name())),info); + } + + + }; + // BinaryOutArchive ====================================================================== class NGCORE_API BinaryOutArchive : public Archive { @@ -159,7 +644,7 @@ namespace ngcore (*this) & GetLibraryVersions(); } TextOutArchive (std::string filename) : - TextOutArchive(std::make_shared(filename.c_str())) { } + TextOutArchive(std::make_shared(filename)) { } const VersionInfo& getVersion(const std::string& library) { return GetLibraryVersions()[library]; } @@ -265,5 +750,6 @@ namespace ngcore return *this; } }; -} -#endif // NG_ARCHIVE_HPP +} // namespace ngcore + +#endif // NETGEN_CORE_ARCHIVE_HPP diff --git a/libsrc/core/basearchive.cpp b/libsrc/core/basearchive.cpp deleted file mode 100644 index ad0d1866..00000000 --- a/libsrc/core/basearchive.cpp +++ /dev/null @@ -1,44 +0,0 @@ - -#include "ngcore.hpp" - -#ifndef WIN -#include -#endif - -namespace ngcore -{ - static std::map library_versions; - std::map& Archive :: GetLibraryVersions() - { - return library_versions; - } - VersionInfo GetLibraryVersion(const std::string& library) - { return library_versions[library]; } - - void SetLibraryVersion(const std::string& library, VersionInfo version) - { library_versions[library] = version; } - -#ifdef WIN - // windows does demangling in typeid(T).name() - std::string demangle(const char* typeinfo) { return typeinfo; } -#else - std::string demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, 0, 0, &status); } -#endif - - static std::map* type_register; - const ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname) - { - if(!type_register) type_register = new std::map(); - return (*type_register)[classname]; - } - void Archive :: SetArchiveRegister(const std::string& classname, ClassArchiveInfo info) - { - if(!type_register) type_register = new std::map(); - (*type_register)[classname] = info; - } - bool Archive :: IsRegistered(const std::string& classname) - { - if(!type_register) type_register = new std::map(); - return type_register->count(classname) != 0; - } -} diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp deleted file mode 100644 index 7e1f7335..00000000 --- a/libsrc/core/basearchive.hpp +++ /dev/null @@ -1,480 +0,0 @@ -#ifndef NG_BASEARCHIVE_HPP -#define NG_BASEARCHIVE_HPP - -namespace ngcore -{ - class VersionInfo; - // Libraries using this archive can store their version here to implement backwards compatibility - VersionInfo GetLibraryVersion(const std::string& library); - void SetLibraryVersion(const std::string& library, VersionInfo version); - - class Archive; - NGCORE_API std::string demangle(const char* typeinfo); - - // create new pointer of type T if it is default constructible, else throw - template - T* constructIfPossible_impl(...) - { throw std::runtime_error(std::string(demangle(typeid(T).name())) + " is not default constructible!"); } - - template::value>::type> - T* constructIfPossible_impl(int) { return new T; } - - template - T* constructIfPossible() { return constructIfPossible_impl(int{}); } - - //Type trait to check if a class implements a 'void DoArchive(Archive&)' function - template - struct has_DoArchive - { - private: - template - static constexpr auto check(T2*) -> - typename std::is_same().DoArchive(std::declval())),void>::type; - template - static constexpr std::false_type check(...); - typedef decltype(check(0)) type; - public: - NGCORE_API static constexpr bool value = type::value; - }; - - // Check if class is archivable - template - struct is_Archivable - { - private: - template - static constexpr auto check(T2*) -> - typename std::is_same() & std::declval()),Archive&>::type; - template - static constexpr std::false_type check(...); - typedef decltype(check(nullptr)) type; - public: - NGCORE_API static constexpr bool value = type::value; - }; - - struct ClassArchiveInfo - { - // create new object of this type and return a void* pointer that is points to the location - // of the (base)class given by type_info - std::function creator; - // This caster takes a void* pointer to the type stored in this info and casts it to a - // void* pointer pointing to the (base)class type_info - std::function upcaster; - // This caster takes a void* pointer to the (base)class type_info and returns void* pointing - // to the type stored in this info - std::function downcaster; - }; - - // Base Archive class - class NGCORE_API Archive - { - bool is_output; - // how many different shared_ptr/pointer have been (un)archived - int shared_ptr_count, ptr_count; - // maps for archived shared pointers and pointers - std::map shared_ptr2nr, ptr2nr; - // vectors for storing the unarchived (shared) pointers - std::vector> nr2shared_ptr; - std::vector nr2ptr; - - // Helper class for up-/downcasting - template - struct Caster - { - static void* tryUpcast(const std::type_info& ti, T* p); - static void* tryDowncast(const std::type_info& ti, void* p); - }; - template - friend class RegisterClassForArchive; - - // Returns ClassArchiveInfo of demangled typeid - static const ClassArchiveInfo& GetArchiveRegister(const std::string& classname); - // Set ClassArchiveInfo for demangled typeid, this is done by creating an instance of - // RegisterClassForArchive - static void SetArchiveRegister(const std::string& classname, ClassArchiveInfo info); - static bool IsRegistered(const std::string& classname); - public: - Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; } - virtual ~Archive() { ; } - - bool Output () { return is_output; } - bool Input () { return !is_output; } - virtual const VersionInfo& getVersion(const std::string& library) = 0; - - // Pure virtual functions that have to be implemented by In-/OutArchive - virtual Archive & operator & (double & d) = 0; - virtual Archive & operator & (int & i) = 0; - virtual Archive & operator & (long & i) = 0; - virtual Archive & operator & (size_t & i) = 0; - virtual Archive & operator & (short & i) = 0; - virtual Archive & operator & (unsigned char & i) = 0; - virtual Archive & operator & (bool & b) = 0; - virtual Archive & operator & (std::string & str) = 0; - virtual Archive & operator & (char *& str) = 0; - - - // Archive std classes ================================================ - template - Archive& operator & (std::complex& c) - { - if(is_output) - (*this) << c.real() << c.imag(); - else - { - T tmp; - (*this) & tmp; - c.real(tmp); - (*this) & tmp; - c.imag(tmp); - } - return (*this); - } - template - Archive& operator & (std::vector& v) - { - size_t size; - if(is_output) - size = v.size(); - (*this) & size; - if(!is_output) - v.resize(size); - Do(&v[0], size); - return (*this); - } - template - Archive& operator& (std::map& map) - { - if(is_output) - { - (*this) << size_t(map.size()); - for(auto& pair : map) - (*this) << pair.first << pair.second; - } - else - { - size_t size; - (*this) & size; - T1 key; T2 val; - for(size_t i = 0; i < size; i++) - { - T1 key; T2 val; - (*this) & key & val; - map[key] = val; - } - } - return (*this); - } - // Archive arrays ===================================================== - // this functions can be overloaded in Archive implementations for more efficiency - template ::value>::type> - Archive & Do (T * data, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; - - virtual Archive & Do (double * d, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; - - virtual Archive & Do (int * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (long * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (size_t * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (short * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (unsigned char * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (bool * b, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; - - // Archive a class implementing a (void DoArchive(Archive&)) method ======= - template::value>> - Archive& operator & (T& val) - { - val.DoArchive(*this); return *this; - } - - // Archive shared_ptrs ================================================= - template - Archive& operator & (std::shared_ptr& ptr) - { - if(Output()) - { - // save -2 for nullptr - if(!ptr) - return (*this) << -2; - - void* reg_ptr = ptr.get(); - bool neededDowncast = false; - // Downcasting is only possible for our registered classes - if(typeid(T) != typeid(*ptr)) - { - if(!IsRegistered(demangle(typeid(*ptr).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + demangle(typeid(*ptr).name()) - + " not registered for archive"); - reg_ptr = GetArchiveRegister(demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); - // if there was a true downcast we have to store more information - if(reg_ptr != (void*) ptr.get()) - neededDowncast = true; - } - auto pos = shared_ptr2nr.find(reg_ptr); - // if not found store -1 and the pointer - if(pos == shared_ptr2nr.end()) - { - auto p = ptr.get(); - (*this) << -1; - (*this) & neededDowncast & p; - // if we did downcast we store the true type as well - if(neededDowncast) - (*this) << demangle(typeid(*ptr).name()); - shared_ptr2nr[reg_ptr] = shared_ptr_count++; - return *this; - } - // if found store the position and if it has to be downcasted and how - (*this) << pos->second << neededDowncast; - if(neededDowncast) - (*this) << demangle(typeid(*ptr).name()); - return (*this); - } - else // Input - { - int nr; - (*this) & nr; - // -2 restores a nullptr - if(nr == -2) - { - ptr = nullptr; - return *this; - } - // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it - else if (nr == -1) - { - T* p; - bool neededDowncast; - (*this) & neededDowncast & p; - ptr = std::shared_ptr(p); - // if we did downcast we need to store a shared_ptr to the true object - if(neededDowncast) - { - std::string name; - (*this) & name; - auto info = GetArchiveRegister(name); - // for this we use an aliasing constructor to create a shared pointer sharing lifetime - // with our shared ptr, but pointing to the true object - nr2shared_ptr.push_back(std::shared_ptr(std::static_pointer_cast(ptr), - info.downcaster(typeid(T), - ptr.get()))); - } - else - nr2shared_ptr.push_back(ptr); - } - else - { - auto other = nr2shared_ptr[nr]; - bool neededDowncast; - (*this) & neededDowncast; - if(neededDowncast) - { - // if there was a downcast we can expect the class to be registered (since archiving - // wouldn't have worked else) - std::string name; - (*this) & name; - auto info = GetArchiveRegister(name); - // same trick as above, create a shared ptr sharing lifetime with - // the shared_ptr in the register, but pointing to our object - ptr = std::static_pointer_cast(std::shared_ptr(other, - info.upcaster(typeid(T), - other.get()))); - } - else - ptr = std::static_pointer_cast(other); - } - } - return *this; - } - - // Archive pointers ======================================================= - template - Archive & operator& (T *& p) - { - if (Output()) - { - // if the pointer is null store -2 - if (!p) - return (*this) << -2; - void* reg_ptr = (void*)p; - if(typeid(T) != typeid(*p)) - { - if(!IsRegistered(demangle(typeid(*p).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + demangle(typeid(*p).name()) - + " not registered for archive"); - else - reg_ptr = GetArchiveRegister(demangle(typeid(*p).name())).downcaster(typeid(T), (void*) p); - } - auto pos = ptr2nr.find(reg_ptr); - // if the pointer is not found in the map create a new entry - if (pos == ptr2nr.end()) - { - ptr2nr[reg_ptr] = ptr_count++; - if(typeid(*p) == typeid(T)) - if (std::is_constructible::value) - { - return (*this) << -1 & (*p); - } - else - throw std::runtime_error(std::string("Archive error: Class ") + - demangle(typeid(*p).name()) + " does not provide a default constructor!"); - else - { - // if a pointer to a base class is archived, the class hierarchy must be registered - // to avoid compile time issues we allow this behaviour only for "our" classes that - // implement a void DoArchive(Archive&) member function - // To recreate the object we need to store the true type of it - if(!IsRegistered(demangle(typeid(*p).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + demangle(typeid(*p).name()) - + " not registered for archive"); - else - return (*this) << -3 << demangle(typeid(*p).name()) & (*p); - } - } - else - { - (*this) & pos->second; - bool downcasted = !(reg_ptr == (void*) p); - // store if the class has been downcasted and the name - (*this) << downcasted << demangle(typeid(*p).name()); - } - } - else - { - int nr; - (*this) & nr; - if (nr == -2) // restore a nullptr - p = nullptr; - else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) - { - p = constructIfPossible(); - nr2ptr.push_back(p); - (*this) & *p; - } - else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... - { - // As stated above, we want this special behaviour only for our classes that implement DoArchive - std::string name; - (*this) & name; - auto info = GetArchiveRegister(name); - // the creator creates a new object of type name, and returns a void* pointing - // to T (which may have an offset) - p = (T*) info.creator(typeid(T)); - // we store the downcasted pointer (to be able to find it again from - // another class in a multiple inheritance tree) - nr2ptr.push_back(info.downcaster(typeid(T),p)); - (*this) & *p; - } - else - { - bool downcasted; - std::string name; - (*this) & downcasted & name; - if(downcasted) - { - // if the class has been downcasted we can assume it is in the register - auto info = GetArchiveRegister(name); - p = (T*) info.upcaster(typeid(T), nr2ptr[nr]); - } - else - p = (T*) nr2ptr[nr]; - } - } - return *this; - } - - // const ptr - template - Archive& operator &(const T*& t) - { - return (*this) & const_cast(t); - } - - // Write a read only variable - template - Archive & operator << (const T & t) - { - T ht(t); - (*this) & ht; - return *this; - } - - virtual void FlushBuffer() {} - - protected: - static std::map& GetLibraryVersions(); - private: - template - struct Caster - { - static void* tryUpcast (const std::type_info& ti, T* p) - { - throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!"); - } - static void* tryDowncast (const std::type_info& ti, void* p) - { - throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!"); - } - }; - - template - struct Caster - { - static void* tryUpcast(const std::type_info& ti, T* p) - { - try - { return GetArchiveRegister(demangle(typeid(B1).name())).upcaster(ti, (void*) (dynamic_cast(p))); } - catch(std::exception) - { return Caster::tryUpcast(ti, p); } - } - - static void* tryDowncast(const std::type_info& ti, void* p) - { - if(typeid(B1) == ti) - return dynamic_cast((B1*) p); - try - { return GetArchiveRegister(demangle(typeid(B1).name())).downcaster(ti, (void*) ((B1*)p)); } - catch(std::exception) - { return Caster::tryDowncast(ti, p); } - } - }; - }; - - template - class NGCORE_API RegisterClassForArchive - { - public: - RegisterClassForArchive() - { - static_assert(all_of_tmpl::value...>, - "Variadic template arguments must be base classes of T"); - ClassArchiveInfo info; - info.creator = [this,&info](const std::type_info& ti) -> void* - { return typeid(T) == ti ? constructIfPossible() - : Archive::Caster::tryUpcast(ti, constructIfPossible()); }; - info.upcaster = [this](const std::type_info& ti, void* p) -> void* - { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, (T*) p); }; - info.downcaster = [this](const std::type_info& ti, void* p) -> void* - { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; - Archive::SetArchiveRegister(std::string(demangle(typeid(T).name())),info); - } - - - }; - -} - -#endif // NG_BASEARCHIVE_HPP diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index 1c364730..1c8fa591 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -1,49 +1,7 @@ -#ifndef NG_CORE_HPP -#define NG_CORE_HPP +#ifndef NETGEN_CORE_NGCORE_HPP +#define NETGEN_CORE_NGCORE_HPP -// std includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 - #define NGCORE_API_EXPORT __declspec(dllexport) - #define NGCORE_API_IMPORT __declspec(dllimport) -#else - #define NGCORE_API_EXPORT - #define NGCORE_API_IMPORT -#endif - -#ifdef NGCORE_EXPORTS - #define NGCORE_API NGCORE_API_EXPORT -#else - #define NGCORE_API NGCORE_API_IMPORT -#endif - -namespace ngcore -{ -#if defined(__GNUC__) - inline bool likely (bool x) { return __builtin_expect((x), true); } - inline bool unlikely (bool x) { return __builtin_expect((x), false); } -#else - inline bool likely (bool x) { return x; } - inline bool unlikely (bool x) { return x; } -#endif -} - -// own includes -#include "type_traits.hpp" -#include "basearchive.hpp" -#include "version.hpp" #include "archive.hpp" +#include "version.hpp" -#endif // NG_CORE_HPP +#endif // NETGEN_CORE_NGCORE_HPP diff --git a/libsrc/core/ngcore_api.hpp b/libsrc/core/ngcore_api.hpp new file mode 100644 index 00000000..c08d0ac9 --- /dev/null +++ b/libsrc/core/ngcore_api.hpp @@ -0,0 +1,29 @@ +#ifndef NETGEN_CORE_NGCORE_API_HPP +#define NETGEN_CORE_NGCORE_API_HPP + +#ifdef WIN32 + #define NGCORE_API_EXPORT __declspec(dllexport) + #define NGCORE_API_IMPORT __declspec(dllimport) +#else + #define NGCORE_API_EXPORT + #define NGCORE_API_IMPORT +#endif + +#ifdef NGCORE_EXPORTS + #define NGCORE_API NGCORE_API_EXPORT +#else + #define NGCORE_API NGCORE_API_IMPORT +#endif + +namespace ngcore +{ +#if defined(__GNUC__) + inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); } + inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); } +#else + inline bool likely (bool x) { return x; } + inline bool unlikely (bool x) { return x; } +#endif +} // namespace ngcore + +#endif // NETGEN_CORE_NGCORE_API_HPP diff --git a/libsrc/core/type_traits.hpp b/libsrc/core/type_traits.hpp index 894a5d07..c298aedc 100644 --- a/libsrc/core/type_traits.hpp +++ b/libsrc/core/type_traits.hpp @@ -1,11 +1,13 @@ #ifndef NGS_TYPE_TRAITS_HPP #define NGS_TYPE_TRAITS_HPP +#include + namespace ngcore { template struct _BoolArray{}; template constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(vals || true)...>>::value; -} +} // namespace ngcore #endif // NGS_TYPE_TRAITS_HPP diff --git a/libsrc/core/version.cpp b/libsrc/core/version.cpp new file mode 100644 index 00000000..7f6bac69 --- /dev/null +++ b/libsrc/core/version.cpp @@ -0,0 +1,11 @@ + +#include "archive.hpp" +#include "version.hpp" + +namespace ngcore +{ + void VersionInfo :: DoArchive(Archive& ar) + { + ar & mayor_ & minor_ & release & patch & git_hash; + } +} // namespace ngcore diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp index f73aad23..f46e74af 100644 --- a/libsrc/core/version.hpp +++ b/libsrc/core/version.hpp @@ -1,8 +1,13 @@ -#ifndef NGS_VERSION_HPP -#define NGS_VERSION_HPP +#ifndef NETGEN_CORE_VERSION_HPP +#define NETGEN_CORE_VERSION_HPP + +#include +#include +#include "ngcore_api.hpp" namespace ngcore { + class Archive; class VersionInfo { private: @@ -78,10 +83,8 @@ namespace ngcore bool operator <=(const VersionInfo& other) const { return !((*this) > other); } bool operator >=(const VersionInfo& other) const { return !((*this) < other); } - void DoArchive(Archive& ar) - { - ar & mayor_ & minor_ & release & patch & git_hash; - } + void DoArchive(Archive& ar); }; -} -#endif // NGS_VERSION_HPP +} // namespace ngcore + +#endif // NETGEN_CORE_VERSION_HPP diff --git a/tests/catch/CMakeLists.txt b/tests/catch/CMakeLists.txt index 53cacdda..fc0ebe41 100644 --- a/tests/catch/CMakeLists.txt +++ b/tests/catch/CMakeLists.txt @@ -28,4 +28,10 @@ endmacro() add_unit_test(archive archive.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) From 6f808cb40f3d161e77982d7599d6ed2c7e16f6c4 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 10 Dec 2018 10:52:00 +0100 Subject: [PATCH 22/46] clang-tidy warnings as errors --- CMakeLists.txt | 2 +- libsrc/core/.clang-tidy | 4 ++++ libsrc/core/archive.hpp | 15 ++++++++------- libsrc/core/version.hpp | 8 ++++---- 4 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 libsrc/core/.clang-tidy diff --git a/CMakeLists.txt b/CMakeLists.txt index 33d2d835..185e3fe5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -360,7 +360,7 @@ if(ENABLE_CPP_CORE_GUIDELINES_CHECK) message(WARNING "clang-tidy not found.") else() message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") - set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-checks=*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-default-arguments") + set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-warnings-as-errors=*" "-header-filter=libsrc/core/") endif() endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy new file mode 100644 index 00000000..c299ae90 --- /dev/null +++ b/libsrc/core/.clang-tidy @@ -0,0 +1,4 @@ +Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion' +CheckOptions: + - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor + value: 1 \ No newline at end of file diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 89656ad5..66589d90 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include #include #include #include @@ -25,12 +25,12 @@ namespace ngcore NGCORE_API std::string demangle(const char* typeinfo); // create new pointer of type T if it is default constructible, else throw - template - T* constructIfPossible_impl(...) + template + T* constructIfPossible_impl(Rest... /*unused*/) { throw std::runtime_error(std::string(demangle(typeid(T).name())) + " is not default constructible!"); } template::value>::type> - T* constructIfPossible_impl(int) { return new T; } + T* constructIfPossible_impl(int /*unused*/) { return new T; } template T* constructIfPossible() { return constructIfPossible_impl(int{}); } @@ -45,7 +45,7 @@ namespace ngcore typename std::is_same().DoArchive(std::declval())),void>::type; template static constexpr std::false_type check(...); - typedef decltype(check(0)) type; + using type = decltype(check(nullptr)); public: NGCORE_API static constexpr bool value = type::value; }; @@ -60,7 +60,7 @@ namespace ngcore typename std::is_same() & std::declval()),Archive&>::type; template static constexpr std::false_type check(...); - typedef decltype(check(nullptr)) type; + using type = decltype(check(nullptr)); public: NGCORE_API static constexpr bool value = type::value; }; @@ -107,7 +107,8 @@ namespace ngcore static void SetArchiveRegister(const std::string& classname, const ClassArchiveInfo& info); static bool IsRegistered(const std::string& classname); public: - Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; } + Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), ptr_count(0) + shared_ptr2nr(), ptr2nr(), nr2shared_ptr(), nr2prt() { ; } virtual ~Archive() { ; } bool Output () { return is_output; } diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp index f46e74af..5ffa8bb0 100644 --- a/libsrc/core/version.hpp +++ b/libsrc/core/version.hpp @@ -53,16 +53,16 @@ namespace ngcore std::string to_string() const { std::string vstring = "v" + std::to_string(mayor_); - if(minor_ || release || patch || git_hash.size()) + if(minor_ || release || patch || !git_hash.empty()) { vstring += "." + std::to_string(minor_); - if(release || patch || git_hash.size()) + if(release || patch || !git_hash.empty()) { vstring += "." + std::to_string(release); - if(patch || git_hash.size()) + if(patch || !git_hash.empty()) { vstring += "-" + std::to_string(patch); - if(git_hash.size()) + if(!git_hash.empty()) vstring += "-" + git_hash; } } From 3679ea7e45ed87cd3cda002e0e8bd1df8fc44fbf Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 10 Dec 2018 10:57:56 +0100 Subject: [PATCH 23/46] Enable core guidelines check, build on Ubuntu 18.04 --- .gitlab-ci.yml | 26 +++++++------------------- tests/build.sh | 2 +- tests/docker_16.04 | 4 ---- tests/{docker_15.10 => dockerfile} | 4 ++-- 4 files changed, 10 insertions(+), 26 deletions(-) delete mode 100644 tests/docker_16.04 rename tests/{docker_15.10 => dockerfile} (75%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9f86836a..c7117fc7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,15 +46,10 @@ stages: - ls - docker info -.template_ubuntu_1510: &ubuntu_1510 +.template_ubuntu: &ubuntu <<: *ubuntu variables: - UBUNTU_VERSION: "15.10" - -.template_ubuntu_1604: &ubuntu_1604 - <<: *ubuntu - variables: - UBUNTU_VERSION: "16.04" + UBUNTU_VERSION: "18.04" ############################################ # Build stage @@ -98,18 +93,14 @@ build_netgen_win64: .template_build_linux: &build_linux stage: build script: - - docker build -t netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} -f tests/docker_${UBUNTU_VERSION} . + - docker build -t netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} -f tests/dockerfile . - rm -f netgen_${CI_BUILD_REF_NAME}_$UBUNTU_VERSION.id - docker run --cidfile netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build.sh - docker commit `cat netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id` netgen_${CI_BUILD_REF_NAME}_installed:${UBUNTU_VERSION} - rm netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id -.build_ubuntu_1510: - <<: *ubuntu_1510 - <<: *build_linux - -build_ubuntu_1604: - <<: *ubuntu_1604 +build_ubuntu: + <<: *ubuntu <<: *build_linux @@ -145,11 +136,8 @@ test_win64: netgen_${CI_BUILD_REF_NAME}_installed:${UBUNTU_VERSION} bash -c 'cd /root/build/netgen && make test_netgen ARGS="-V"' -.test_ubuntu_1510: - <<: *ubuntu_1510 - <<: *test_linux -test_ubuntu_1604: - <<: *ubuntu_1604 +test_ubuntu: + <<: *ubuntu <<: *test_linux ############################################ diff --git a/tests/build.sh b/tests/build.sh index 68aea3ad..d2727b2c 100755 --- a/tests/build.sh +++ b/tests/build.sh @@ -1,6 +1,6 @@ cd mkdir -p build/netgen cd build/netgen -cmake ../../src/netgen -DUSE_CCACHE=ON +cmake ../../src/netgen -DUSE_CCACHE=ON -DENABLE_CPP_CORE_GUIDELINES_CHECK=ON make -j12 make install diff --git a/tests/docker_16.04 b/tests/docker_16.04 deleted file mode 100644 index 2195714b..00000000 --- a/tests/docker_16.04 +++ /dev/null @@ -1,4 +0,0 @@ -FROM ubuntu:16.04 -MAINTAINER Matthias Hochsteger -RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk -ADD . /root/src/netgen diff --git a/tests/docker_15.10 b/tests/dockerfile similarity index 75% rename from tests/docker_15.10 rename to tests/dockerfile index b386f250..b215db7a 100644 --- a/tests/docker_15.10 +++ b/tests/dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:15.10 +FROM ubuntu:18.04 MAINTAINER Matthias Hochsteger -RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk +RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk clang-tidy ADD . /root/src/netgen From 6a2361700fd0499b26b8b0c0c1285e44ee7e77b2 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 10 Dec 2018 10:59:46 +0100 Subject: [PATCH 24/46] Fix typo --- libsrc/core/archive.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 66589d90..25e3482c 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -107,8 +107,10 @@ namespace ngcore static void SetArchiveRegister(const std::string& classname, const ClassArchiveInfo& info); static bool IsRegistered(const std::string& classname); public: - Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), ptr_count(0) - shared_ptr2nr(), ptr2nr(), nr2shared_ptr(), nr2prt() { ; } + Archive (bool ais_output) : + is_output(ais_output), shared_ptr_count(0), ptr_count(0), + shared_ptr2nr(), ptr2nr(), nr2shared_ptr(), nr2ptr() { ; } + virtual ~Archive() { ; } bool Output () { return is_output; } From 99165270971581413f6fa6997b6989632bfd306c Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 10 Dec 2018 11:10:31 +0100 Subject: [PATCH 25/46] Fix warning --- libsrc/core/archive.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 25e3482c..d39e3f17 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -108,8 +108,7 @@ namespace ngcore static bool IsRegistered(const std::string& classname); public: Archive (bool ais_output) : - is_output(ais_output), shared_ptr_count(0), ptr_count(0), - shared_ptr2nr(), ptr2nr(), nr2shared_ptr(), nr2ptr() { ; } + is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; } virtual ~Archive() { ; } From 0c4fbda22aa0edceb26ef9f48b8a606aa406444d Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 10 Dec 2018 11:18:35 +0100 Subject: [PATCH 26/46] Fix dockerfile --- tests/dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/dockerfile b/tests/dockerfile index b215db7a..40152059 100644 --- a/tests/dockerfile +++ b/tests/dockerfile @@ -1,4 +1,5 @@ FROM ubuntu:18.04 +ENV DEBIAN_FRONTEND=noninteractive MAINTAINER Matthias Hochsteger RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk clang-tidy ADD . /root/src/netgen From 0093dab1be3a8638c6efc56028e0b32dad43e580 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 10 Dec 2018 11:30:45 +0100 Subject: [PATCH 27/46] Use C++ casts --- libsrc/core/.clang-tidy | 2 +- libsrc/core/archive.hpp | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index c299ae90..81b0a6ae 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -1,4 +1,4 @@ Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion' CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor - value: 1 \ No newline at end of file + value: 1 diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index d39e3f17..8bdfe0f1 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -234,7 +234,7 @@ namespace ngcore + " not registered for archive"); reg_ptr = GetArchiveRegister(demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); // if there was a true downcast we have to store more information - if(reg_ptr != (void*) ptr.get()) + if(reg_ptr != static_cast(ptr.get()) ) neededDowncast = true; } auto pos = shared_ptr2nr.find(reg_ptr); @@ -322,7 +322,7 @@ namespace ngcore // if the pointer is null store -2 if (!p) return (*this) << -2; - void* reg_ptr = (void*)p; + void* reg_ptr = static_cast(p); if(typeid(T) != typeid(*p)) { if(!IsRegistered(demangle(typeid(*p).name()))) @@ -330,7 +330,7 @@ namespace ngcore + demangle(typeid(*p).name()) + " not registered for archive"); else - reg_ptr = GetArchiveRegister(demangle(typeid(*p).name())).downcaster(typeid(T), (void*) p); + reg_ptr = GetArchiveRegister(demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry @@ -362,7 +362,7 @@ namespace ngcore else { (*this) & pos->second; - bool downcasted = !(reg_ptr == (void*) p); + bool downcasted = !(reg_ptr == static_cast(p) ); // store if the class has been downcasted and the name (*this) << downcasted << demangle(typeid(*p).name()); } @@ -387,7 +387,7 @@ namespace ngcore auto info = GetArchiveRegister(name); // the creator creates a new object of type name, and returns a void* pointing // to T (which may have an offset) - p = (T*) info.creator(typeid(T)); + p = dynamic_cast(info.creator(typeid(T))); // we store the downcasted pointer (to be able to find it again from // another class in a multiple inheritance tree) nr2ptr.push_back(info.downcaster(typeid(T),p)); @@ -402,10 +402,10 @@ namespace ngcore { // if the class has been downcasted we can assume it is in the register auto info = GetArchiveRegister(name); - p = (T*) info.upcaster(typeid(T), nr2ptr[nr]); + p = dynamic_cast(info.upcaster(typeid(T), nr2ptr[nr])); } else - p = (T*) nr2ptr[nr]; + p = dynamic_cast(nr2ptr[nr]); } } return *this; @@ -451,7 +451,7 @@ namespace ngcore static void* tryUpcast(const std::type_info& ti, T* p) { try - { return GetArchiveRegister(demangle(typeid(B1).name())).upcaster(ti, (void*) (dynamic_cast(p))); } + { return GetArchiveRegister(demangle(typeid(B1).name())).upcaster(ti, static_cast(dynamic_cast(p))); } catch(std::exception) { return Caster::tryUpcast(ti, p); } } @@ -459,9 +459,9 @@ namespace ngcore static void* tryDowncast(const std::type_info& ti, void* p) { if(typeid(B1) == ti) - return dynamic_cast((B1*) p); + return dynamic_cast(dynamic_cast(p)); try - { return GetArchiveRegister(demangle(typeid(B1).name())).downcaster(ti, (void*) ((B1*)p)); } + { return GetArchiveRegister(demangle(typeid(B1).name())).downcaster(ti, static_cast(dynamic_cast(p))); } catch(std::exception) { return Caster::tryDowncast(ti, p); } } @@ -481,7 +481,7 @@ namespace ngcore { return typeid(T) == ti ? constructIfPossible() : Archive::Caster::tryUpcast(ti, constructIfPossible()); }; info.upcaster = [this](const std::type_info& ti, void* p) -> void* - { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, (T*) p); }; + { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, dynamic_cast(p)); }; info.downcaster = [this](const std::type_info& ti, void* p) -> void* { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; Archive::SetArchiveRegister(std::string(demangle(typeid(T).name())),info); @@ -558,11 +558,11 @@ namespace ngcore if (unlikely(ptr > BUFFERSIZE-sizeof(T))) { fout->write(&buffer[0], ptr); - * (T*) (&buffer[0]) = x; + *dynamic_cast(&buffer[0]) = x; ptr = sizeof(T); return *this; } - * (T*) (&buffer[ptr]) = x; + *dynamic_cast(&buffer[ptr]) = x; ptr += sizeof(T); return *this; } From 0ef2d0f7f9facd7e3ddbad82a9db5946e282937a Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 10 Dec 2018 11:49:38 +0100 Subject: [PATCH 28/46] fixes for core guidelines checks --- libsrc/core/.clang-tidy | 4 +- libsrc/core/archive.hpp | 88 ++++++++++++++++++------------------- libsrc/core/type_traits.hpp | 8 ++-- libsrc/core/version.hpp | 24 +++++----- 4 files changed, 62 insertions(+), 62 deletions(-) diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index 81b0a6ae..6d5e34da 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -1,4 +1,4 @@ -Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion' +Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions' CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor - value: 1 + value: 1 \ No newline at end of file diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 8bdfe0f1..7efc2d9d 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -506,25 +506,25 @@ namespace ngcore : BinaryOutArchive(std::make_shared(filename)) {} virtual ~BinaryOutArchive () { FlushBuffer(); } - const VersionInfo& getVersion(const std::string& library) + const VersionInfo& getVersion(const std::string& library) override { return GetLibraryVersions()[library]; } using Archive::operator&; - virtual Archive & operator & (double & d) + Archive & operator & (double & d) override { return Write(d); } - virtual Archive & operator & (int & i) + Archive & operator & (int & i) override { return Write(i); } - virtual Archive & operator & (short & i) + Archive & operator & (short & i) override { return Write(i); } - virtual Archive & operator & (long & i) + Archive & operator & (long & i) override { return Write(i); } - virtual Archive & operator & (size_t & i) + Archive & operator & (size_t & i) override { return Write(i); } - virtual Archive & operator & (unsigned char & i) + Archive & operator & (unsigned char & i) override { return Write(i); } - virtual Archive & operator & (bool & b) + Archive & operator & (bool & b) override { return Write(b); } - virtual Archive & operator & (std::string & str) + Archive & operator & (std::string & str) override { int len = str.length(); (*this) & len; @@ -533,7 +533,7 @@ namespace ngcore fout->write (&str[0], len); return *this; } - virtual Archive & operator & (char *& str) + Archive & operator & (char *& str) override { long len = str ? strlen (str) : -1; (*this) & len; @@ -542,7 +542,7 @@ namespace ngcore fout->write (&str[0], len); return *this; } - void FlushBuffer() + void FlushBuffer() override { if (ptr > 0) { @@ -581,25 +581,25 @@ namespace ngcore BinaryInArchive (std::string filename) : BinaryInArchive(std::make_shared(filename)) { ; } - const VersionInfo& getVersion(const std::string& library) + const VersionInfo& getVersion(const std::string& library) override { return vinfo[library]; } using Archive::operator&; - virtual Archive & operator & (double & d) + Archive & operator & (double & d) override { Read(d); return *this; } - virtual Archive & operator & (int & i) + Archive & operator & (int & i) override { Read(i); return *this; } - virtual Archive & operator & (short & i) + Archive & operator & (short & i) override { Read(i); return *this; } - virtual Archive & operator & (long & i) + Archive & operator & (long & i) override { Read(i); return *this; } - virtual Archive & operator & (size_t & i) + Archive & operator & (size_t & i) override { Read(i); return *this; } - virtual Archive & operator & (unsigned char & i) + Archive & operator & (unsigned char & i) override { Read(i); return *this; } - virtual Archive & operator & (bool & b) + Archive & operator & (bool & b) override { Read(b); return *this; } - virtual Archive & operator & (std::string & str) + Archive & operator & (std::string & str) override { int len; (*this) & len; @@ -608,7 +608,7 @@ namespace ngcore fin->read(&str[0], len); return *this; } - virtual Archive & operator & (char *& str) + Archive & operator & (char *& str) override { long len; (*this) & len; @@ -623,11 +623,11 @@ namespace ngcore return *this; } - virtual Archive & Do (double * d, size_t n) + Archive & Do (double * d, size_t n) override { fin->read(reinterpret_cast(d), n*sizeof(double)); return *this; } - virtual Archive & Do (int * i, size_t n) + Archive & Do (int * i, size_t n) override { fin->read(reinterpret_cast(i), n*sizeof(int)); return *this; } - virtual Archive & Do (size_t * i, size_t n) + Archive & Do (size_t * i, size_t n) override { fin->read(reinterpret_cast(i), n*sizeof(size_t)); return *this; } private: @@ -648,25 +648,25 @@ namespace ngcore TextOutArchive (std::string filename) : TextOutArchive(std::make_shared(filename)) { } - const VersionInfo& getVersion(const std::string& library) + const VersionInfo& getVersion(const std::string& library) override { return GetLibraryVersions()[library]; } using Archive::operator&; - virtual Archive & operator & (double & d) + Archive & operator & (double & d) override { *fout << d << '\n'; return *this; } - virtual Archive & operator & (int & i) + Archive & operator & (int & i) override { *fout << i << '\n'; return *this; } - virtual Archive & operator & (short & i) + Archive & operator & (short & i) override { *fout << i << '\n'; return *this; } - virtual Archive & operator & (long & i) + Archive & operator & (long & i) override { *fout << i << '\n'; return *this; } - virtual Archive & operator & (size_t & i) + Archive & operator & (size_t & i) override { *fout << i << '\n'; return *this; } - virtual Archive & operator & (unsigned char & i) + Archive & operator & (unsigned char & i) override { *fout << int(i) << '\n'; return *this; } - virtual Archive & operator & (bool & b) + Archive & operator & (bool & b) override { *fout << (b ? 't' : 'f') << '\n'; return *this; } - virtual Archive & operator & (std::string & str) + Archive & operator & (std::string & str) override { int len = str.length(); *fout << len << '\n'; @@ -677,7 +677,7 @@ namespace ngcore } return *this; } - virtual Archive & operator & (char *& str) + Archive & operator & (char *& str) override { long len = str ? strlen (str) : -1; *this & len; @@ -703,25 +703,25 @@ namespace ngcore TextInArchive (std::string filename) : TextInArchive(std::make_shared(filename)) {} - const VersionInfo& getVersion(const std::string& library) + const VersionInfo& getVersion(const std::string& library) override { return vinfo[library]; } using Archive::operator&; - virtual Archive & operator & (double & d) + Archive & operator & (double & d) override { *fin >> d; return *this; } - virtual Archive & operator & (int & i) + Archive & operator & (int & i) override { *fin >> i; return *this; } - virtual Archive & operator & (short & i) + Archive & operator & (short & i) override { *fin >> i; return *this; } - virtual Archive & operator & (long & i) + Archive & operator & (long & i) override { *fin >> i; return *this; } - virtual Archive & operator & (size_t & i) + Archive & operator & (size_t & i) override { *fin >> i; return *this; } - virtual Archive & operator & (unsigned char & i) + Archive & operator & (unsigned char & i) override { int _i; *fin >> _i; i = _i; return *this; } - virtual Archive & operator & (bool & b) + Archive & operator & (bool & b) override { char c; *fin >> c; b = (c=='t'); return *this; } - virtual Archive & operator & (std::string & str) + Archive & operator & (std::string & str) override { int len; *fin >> len; @@ -732,7 +732,7 @@ namespace ngcore fin->get(&str[0], len+1, '\0'); return *this; } - virtual Archive & operator & (char *& str) + Archive & operator & (char *& str) override { long len; (*this) & len; diff --git a/libsrc/core/type_traits.hpp b/libsrc/core/type_traits.hpp index c298aedc..36315e7a 100644 --- a/libsrc/core/type_traits.hpp +++ b/libsrc/core/type_traits.hpp @@ -1,5 +1,5 @@ -#ifndef NGS_TYPE_TRAITS_HPP -#define NGS_TYPE_TRAITS_HPP +#ifndef NETGEN_LIBSRC_CORE_TYPE_TRAITS_HPP +#define NETGEN_LIBSRC_CORE_TYPE_TRAITS_HPP #include @@ -7,7 +7,7 @@ namespace ngcore { template struct _BoolArray{}; template - constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(vals || true)...>>::value; + constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(vals || true)...>>::value; // NOLINT } // namespace ngcore -#endif // NGS_TYPE_TRAITS_HPP +#endif // NETGEN_LIBSRC_CORE_TYPE_TRAITS_HPP diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp index 5ffa8bb0..27828e6e 100644 --- a/libsrc/core/version.hpp +++ b/libsrc/core/version.hpp @@ -1,9 +1,9 @@ #ifndef NETGEN_CORE_VERSION_HPP #define NETGEN_CORE_VERSION_HPP +#include "ngcore_api.hpp" #include #include -#include "ngcore_api.hpp" namespace ngcore { @@ -11,39 +11,39 @@ namespace ngcore class VersionInfo { private: - size_t mayor_, minor_, release, patch; - std::string git_hash; + size_t mayor_{}, minor_{}, release{}, patch{}; + std::string git_hash{}; public: - VersionInfo() : mayor_(0), minor_(0), release(0), patch(0), git_hash("") {} + VersionInfo() = default; VersionInfo(std::string vstring) { minor_ = release = patch = 0; git_hash = ""; if(vstring.substr(0,1) == "v") vstring = vstring.substr(1,vstring.size()-1); - auto dot = vstring.find("."); + auto dot = vstring.find('.'); mayor_ = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1, vstring.size()-dot-1); - if(vstring.size()) + if(!vstring.empty()) { - dot = vstring.find("."); + dot = vstring.find('.'); minor_ = std::stoi(vstring.substr(0,dot)); if (dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1, vstring.size()-dot-1); - if(vstring.size()) + if(!vstring.empty()) { - dot = vstring.find("-"); + dot = vstring.find('-'); release = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1,vstring.size()-dot-1); - if(vstring.size()) + if(!vstring.empty()) { - dot = vstring.find("-"); + dot = vstring.find('-'); patch = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1, vstring.size()-dot-1); - if(vstring.size()) + if(!vstring.empty()) git_hash = vstring; } } From b0d15ee29e6513452fde08dd245ac0ff523aac11 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 10 Dec 2018 11:50:36 +0100 Subject: [PATCH 29/46] Fix casts --- libsrc/core/archive.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 7efc2d9d..a72d4dde 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -387,7 +387,7 @@ namespace ngcore auto info = GetArchiveRegister(name); // the creator creates a new object of type name, and returns a void* pointing // to T (which may have an offset) - p = dynamic_cast(info.creator(typeid(T))); + p = static_cast(info.creator(typeid(T))); // we store the downcasted pointer (to be able to find it again from // another class in a multiple inheritance tree) nr2ptr.push_back(info.downcaster(typeid(T),p)); @@ -402,10 +402,10 @@ namespace ngcore { // if the class has been downcasted we can assume it is in the register auto info = GetArchiveRegister(name); - p = dynamic_cast(info.upcaster(typeid(T), nr2ptr[nr])); + p = static_cast(info.upcaster(typeid(T), nr2ptr[nr])); } else - p = dynamic_cast(nr2ptr[nr]); + p = static_cast(nr2ptr[nr]); } } return *this; @@ -459,7 +459,7 @@ namespace ngcore static void* tryDowncast(const std::type_info& ti, void* p) { if(typeid(B1) == ti) - return dynamic_cast(dynamic_cast(p)); + return dynamic_cast(static_cast(p)); try { return GetArchiveRegister(demangle(typeid(B1).name())).downcaster(ti, static_cast(dynamic_cast(p))); } catch(std::exception) @@ -481,7 +481,7 @@ namespace ngcore { return typeid(T) == ti ? constructIfPossible() : Archive::Caster::tryUpcast(ti, constructIfPossible()); }; info.upcaster = [this](const std::type_info& ti, void* p) -> void* - { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, dynamic_cast(p)); }; + { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, static_cast(p)); }; info.downcaster = [this](const std::type_info& ti, void* p) -> void* { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; Archive::SetArchiveRegister(std::string(demangle(typeid(T).name())),info); @@ -558,11 +558,11 @@ namespace ngcore if (unlikely(ptr > BUFFERSIZE-sizeof(T))) { fout->write(&buffer[0], ptr); - *dynamic_cast(&buffer[0]) = x; + *static_cast(&buffer[0]) = x; ptr = sizeof(T); return *this; } - *dynamic_cast(&buffer[ptr]) = x; + *static_cast(&buffer[ptr]) = x; ptr += sizeof(T); return *this; } From 6335398341b262a73ec58b5caf81141f72993d8b Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 10 Dec 2018 13:32:03 +0100 Subject: [PATCH 30/46] fix compile error, some lint --- libsrc/core/archive.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index a72d4dde..0b87e843 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -415,7 +415,7 @@ namespace ngcore template Archive& operator &(const T*& t) { - return (*this) & const_cast(t); + return (*this) & const_cast(t); // NOLINT } // Write a read only variable @@ -435,11 +435,11 @@ namespace ngcore template struct Caster { - static void* tryUpcast (const std::type_info& ti, T* p) + static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/) { throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!"); } - static void* tryDowncast (const std::type_info& ti, void* p) + static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/) { throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!"); } @@ -495,7 +495,7 @@ namespace ngcore { size_t ptr = 0; enum { BUFFERSIZE = 1024 }; - char buffer[BUFFERSIZE]; + char buffer[BUFFERSIZE] alignas(64); std::shared_ptr fout; public: BinaryOutArchive(std::shared_ptr afout) : Archive(true), fout(afout) @@ -558,11 +558,11 @@ namespace ngcore if (unlikely(ptr > BUFFERSIZE-sizeof(T))) { fout->write(&buffer[0], ptr); - *static_cast(&buffer[0]) = x; + *reinterpret_cast(&buffer[0]) = x; // NOLINT ptr = sizeof(T); return *this; } - *static_cast(&buffer[ptr]) = x; + *reinterpret_cast(&buffer[ptr]) = x; // NOLINT ptr += sizeof(T); return *this; } From b28cfcc332734e263efd4bf44438c5d433a3415e Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 10 Dec 2018 14:37:27 +0100 Subject: [PATCH 31/46] fix casting, fix rest of core guidelines --- libsrc/core/.clang-tidy | 4 +- libsrc/core/archive.cpp | 6 ++ libsrc/core/archive.hpp | 134 ++++++++++++++++++++++------------------ libsrc/core/version.hpp | 3 +- 4 files changed, 85 insertions(+), 62 deletions(-) diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index 6d5e34da..65b4984d 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -1,4 +1,4 @@ -Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions' +Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard' CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor - value: 1 \ No newline at end of file + value: 1 diff --git a/libsrc/core/archive.cpp b/libsrc/core/archive.cpp index 9fe54704..1e45bfb4 100644 --- a/libsrc/core/archive.cpp +++ b/libsrc/core/archive.cpp @@ -1,4 +1,10 @@ +#include // for function +#include // for runtime_error +#include // for declval, enable_if, false_type, is_co... +#include // for type_info +#include // for move, swap, pair + #include "archive.hpp" #ifndef WIN32 diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 0b87e843..45fb31f5 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -1,19 +1,22 @@ #ifndef NETGEN_CORE_ARCHIVE_HPP #define NETGEN_CORE_ARCHIVE_HPP -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include // for complex +#include // for size_t, strlen +#include // for operator<<, ifstream, ofstream, basic... +#include // for function +#include // for map, _Rb_tree_iterator +#include // for __shared_ptr_access, __shared_ptr_acc... +#include // for runtime_error +#include // for string, operator+ +#include // for declval, enable_if, false_type, is_co... +#include // for type_info +#include // for move, swap, pair +#include // for vector -#include "ngcore_api.hpp" -#include "type_traits.hpp" -#include "version.hpp" +#include "ngcore_api.hpp" // for NGCORE_API, unlikely +#include "type_traits.hpp" // for all_of_tmpl +#include "version.hpp" // for VersionInfo namespace ngcore { @@ -30,7 +33,7 @@ namespace ngcore { throw std::runtime_error(std::string(demangle(typeid(T).name())) + " is not default constructible!"); } template::value>::type> - T* constructIfPossible_impl(int /*unused*/) { return new T; } + T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT template T* constructIfPossible() { return constructIfPossible_impl(int{}); } @@ -45,7 +48,7 @@ namespace ngcore typename std::is_same().DoArchive(std::declval())),void>::type; template static constexpr std::false_type check(...); - using type = decltype(check(nullptr)); + using type = decltype(check(nullptr)); // NOLINT public: NGCORE_API static constexpr bool value = type::value; }; @@ -60,7 +63,7 @@ namespace ngcore typename std::is_same() & std::declval()),Archive&>::type; template static constexpr std::false_type check(...); - using type = decltype(check(nullptr)); + using type = decltype(check(nullptr)); // NOLINT public: NGCORE_API static constexpr bool value = type::value; }; @@ -107,11 +110,17 @@ namespace ngcore static void SetArchiveRegister(const std::string& classname, const ClassArchiveInfo& info); static bool IsRegistered(const std::string& classname); public: + Archive() = delete; + Archive(const Archive&) = delete; + Archive(Archive&&) = delete; Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; } virtual ~Archive() { ; } + Archive& operator=(const Archive&) = delete; + Archive& operator=(Archive&&) = delete; + bool Output () { return is_output; } bool Input () { return !is_output; } virtual const VersionInfo& getVersion(const std::string& library) = 0; @@ -183,28 +192,28 @@ namespace ngcore // this functions can be overloaded in Archive implementations for more efficiency template ::value>::type> Archive & Do (T * data, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; + { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; // NOLINT virtual Archive & Do (double * d, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; + { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; // NOLINT virtual Archive & Do (int * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT virtual Archive & Do (long * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT virtual Archive & Do (size_t * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT virtual Archive & Do (short * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT virtual Archive & Do (unsigned char * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT virtual Archive & Do (bool * b, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; + { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; // NOLINT // Archive a class implementing a (void DoArchive(Archive&)) method ======= template::value>> @@ -254,7 +263,6 @@ namespace ngcore (*this) << pos->second << neededDowncast; if(neededDowncast) (*this) << demangle(typeid(*ptr).name()); - return (*this); } else // Input { @@ -267,7 +275,7 @@ namespace ngcore return *this; } // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it - else if (nr == -1) + if (nr == -1) { T* p; bool neededDowncast; @@ -329,8 +337,7 @@ namespace ngcore throw std::runtime_error(std::string("Archive error: Polymorphic type ") + demangle(typeid(*p).name()) + " not registered for archive"); - else - reg_ptr = GetArchiveRegister(demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); + reg_ptr = GetArchiveRegister(demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry @@ -355,8 +362,7 @@ namespace ngcore throw std::runtime_error(std::string("Archive error: Polymorphic type ") + demangle(typeid(*p).name()) + " not registered for archive"); - else - return (*this) << -3 << demangle(typeid(*p).name()) & (*p); + return (*this) << -3 << demangle(typeid(*p).name()) & (*p); } } else @@ -452,7 +458,7 @@ namespace ngcore { try { return GetArchiveRegister(demangle(typeid(B1).name())).upcaster(ti, static_cast(dynamic_cast(p))); } - catch(std::exception) + catch(std::exception&) { return Caster::tryUpcast(ti, p); } } @@ -461,8 +467,8 @@ namespace ngcore if(typeid(B1) == ti) return dynamic_cast(static_cast(p)); try - { return GetArchiveRegister(demangle(typeid(B1).name())).downcaster(ti, static_cast(dynamic_cast(p))); } - catch(std::exception) + { return GetArchiveRegister(demangle(typeid(B1).name())).downcaster(ti, static_cast(dynamic_cast(static_cast(p)))); } + catch(std::exception&) { return Caster::tryDowncast(ti, p); } } }; @@ -494,17 +500,24 @@ namespace ngcore class NGCORE_API BinaryOutArchive : public Archive { size_t ptr = 0; - enum { BUFFERSIZE = 1024 }; - char buffer[BUFFERSIZE] alignas(64); + static constexpr size_t BUFFERSIZE = 1024; + alignas(64) char buffer[BUFFERSIZE] = {}; std::shared_ptr fout; public: - BinaryOutArchive(std::shared_ptr afout) : Archive(true), fout(afout) + BinaryOutArchive() = delete; + BinaryOutArchive(const BinaryOutArchive&) = delete; + BinaryOutArchive(BinaryOutArchive&&) = delete; + BinaryOutArchive(std::shared_ptr&& afout) + : Archive(true), fout(std::move(afout)) { (*this) & GetLibraryVersions(); } - BinaryOutArchive(std::string filename) + BinaryOutArchive(const std::string& filename) : BinaryOutArchive(std::make_shared(filename)) {} - virtual ~BinaryOutArchive () { FlushBuffer(); } + ~BinaryOutArchive () override { FlushBuffer(); } + + BinaryOutArchive& operator=(const BinaryOutArchive&) = delete; + BinaryOutArchive& operator=(BinaryOutArchive&&) = delete; const VersionInfo& getVersion(const std::string& library) override { return GetLibraryVersions()[library]; } @@ -539,7 +552,7 @@ namespace ngcore (*this) & len; FlushBuffer(); if(len > 0) - fout->write (&str[0], len); + fout->write (&str[0], len); // NOLINT return *this; } void FlushBuffer() override @@ -571,14 +584,15 @@ namespace ngcore // BinaryInArchive ====================================================================== class NGCORE_API BinaryInArchive : public Archive { - std::map vinfo; + std::map vinfo{}; std::shared_ptr fin; public: - BinaryInArchive (std::shared_ptr afin) : Archive(false), fin(afin) + BinaryInArchive (std::shared_ptr&& afin) + : Archive(false), fin(std::move(afin)) { (*this) & vinfo; } - BinaryInArchive (std::string filename) + BinaryInArchive (const std::string& filename) : BinaryInArchive(std::make_shared(filename)) { ; } const VersionInfo& getVersion(const std::string& library) override @@ -605,7 +619,7 @@ namespace ngcore (*this) & len; str.resize(len); if(len) - fin->read(&str[0], len); + fin->read(&str[0], len); // NOLINT return *this; } Archive & operator & (char *& str) override @@ -616,24 +630,24 @@ namespace ngcore str = nullptr; else { - str = new char[len+1]; - fin->read(&str[0], len); - str[len] = '\0'; + str = new char[len+1]; // NOLINT + fin->read(&str[0], len); // NOLINT + str[len] = '\0'; // NOLINT } return *this; } Archive & Do (double * d, size_t n) override - { fin->read(reinterpret_cast(d), n*sizeof(double)); return *this; } + { fin->read(reinterpret_cast(d), n*sizeof(double)); return *this; } // NOLINT Archive & Do (int * i, size_t n) override - { fin->read(reinterpret_cast(i), n*sizeof(int)); return *this; } + { fin->read(reinterpret_cast(i), n*sizeof(int)); return *this; } // NOLINT Archive & Do (size_t * i, size_t n) override - { fin->read(reinterpret_cast(i), n*sizeof(size_t)); return *this; } + { fin->read(reinterpret_cast(i), n*sizeof(size_t)); return *this; } // NOLINT private: template inline void Read(T& val) - { fin->read(reinterpret_cast(&val), sizeof(T)); } + { fin->read(reinterpret_cast(&val), sizeof(T)); } // NOLINT }; // TextOutArchive ====================================================================== @@ -641,11 +655,12 @@ namespace ngcore { std::shared_ptr fout; public: - TextOutArchive (std::shared_ptr afout) : Archive(true), fout(afout) + TextOutArchive (std::shared_ptr&& afout) + : Archive(true), fout(std::move(afout)) { (*this) & GetLibraryVersions(); } - TextOutArchive (std::string filename) : + TextOutArchive (const std::string& filename) : TextOutArchive(std::make_shared(filename)) { } const VersionInfo& getVersion(const std::string& library) override @@ -672,7 +687,7 @@ namespace ngcore *fout << len << '\n'; if(len) { - fout->write(&str[0], len); + fout->write(&str[0], len); // NOLINT *fout << '\n'; } return *this; @@ -683,7 +698,7 @@ namespace ngcore *this & len; if(len > 0) { - fout->write (&str[0], len); + fout->write (&str[0], len); // NOLINT *fout << '\n'; } return *this; @@ -693,14 +708,15 @@ namespace ngcore // TextInArchive ====================================================================== class NGCORE_API TextInArchive : public Archive { - std::map vinfo; + std::map vinfo{}; std::shared_ptr fin; public: - TextInArchive (std::shared_ptr afin) : Archive(false), fin(afin) + TextInArchive (std::shared_ptr&& afin) : + Archive(false), fin(std::move(afin)) { (*this) & vinfo; } - TextInArchive (std::string filename) + TextInArchive (const std::string& filename) : TextInArchive(std::make_shared(filename)) {} const VersionInfo& getVersion(const std::string& library) override @@ -742,13 +758,13 @@ namespace ngcore str = nullptr; return (*this); } - str = new char[len+1]; + str = new char[len+1]; // NOLINT if(len) { fin->get(ch); // \n - fin->get(&str[0], len+1, '\0'); + fin->get(&str[0], len+1, '\0'); // NOLINT } - str[len] = '\0'; + str[len] = '\0'; // NOLINT return *this; } }; diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp index 27828e6e..ab14d74a 100644 --- a/libsrc/core/version.hpp +++ b/libsrc/core/version.hpp @@ -1,10 +1,11 @@ #ifndef NETGEN_CORE_VERSION_HPP #define NETGEN_CORE_VERSION_HPP -#include "ngcore_api.hpp" #include #include +#include "ngcore_api.hpp" + namespace ngcore { class Archive; From 60d4ef13bac39a1021e44b6b1daeb977ac3e6ba3 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 10 Dec 2018 16:20:07 +0100 Subject: [PATCH 32/46] fix warning as errors outside of ngcore --- CMakeLists.txt | 2 +- libsrc/core/.clang-tidy | 1 + tests/catch/archive.cpp | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 185e3fe5..14931c4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -360,7 +360,7 @@ if(ENABLE_CPP_CORE_GUIDELINES_CHECK) message(WARNING "clang-tidy not found.") else() message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") - set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-warnings-as-errors=*" "-header-filter=libsrc/core/") + set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-header-filter=libsrc/core/") endif() endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index 65b4984d..290188fb 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -2,3 +2,4 @@ Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 +WarningsAsErrors: '*' \ No newline at end of file diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index f5d38eb2..a5ca80d5 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -97,8 +97,8 @@ void testNullPtr(Archive& in, Archive& out) shared_ptr sp = nullptr; out & p & sp; out.FlushBuffer(); - SharedPtrHolder* pin; - shared_ptr spin; + SharedPtrHolder* pin = nullptr; + shared_ptr spin = nullptr; in & pin & spin; CHECK(pin == nullptr); CHECK(spin == nullptr); @@ -186,8 +186,8 @@ void testMultipleInheritance(Archive& in, Archive& out) { out & p & p2; out.FlushBuffer(); - PtrHolder* pin; - SharedPtrHolder* pin2; + PtrHolder* pin = nullptr; + SharedPtrHolder* pin2 = nullptr; in & pin & pin2; checkPtr(pin, pin2); } From 83df85f2743f4fbcc1fc851987801ddeb7af682c Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 12 Dec 2018 11:05:17 +0100 Subject: [PATCH 33/46] detail namespace, linking ngcore to nglib --- libsrc/core/archive.cpp | 16 ++-- libsrc/core/archive.hpp | 176 ++++++++++++++++++++------------------- libsrc/general/array.hpp | 2 +- nglib/CMakeLists.txt | 2 + tests/catch/archive.cpp | 2 +- 5 files changed, 103 insertions(+), 95 deletions(-) diff --git a/libsrc/core/archive.cpp b/libsrc/core/archive.cpp index 1e45bfb4..5a526444 100644 --- a/libsrc/core/archive.cpp +++ b/libsrc/core/archive.cpp @@ -32,32 +32,32 @@ namespace ngcore #ifdef WIN // windows does demangling in typeid(T).name() - std::string demangle(const char* typeinfo) { return typeinfo; } + std::string Demangle(const char* typeinfo) { return typeinfo; } #else - std::string demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, + std::string Demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, nullptr, nullptr, &status); } #endif // clang-tidy should ignore this static object - static std::unique_ptr> type_register; // NOLINT - const ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname) + static std::unique_ptr> type_register; // NOLINT + const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname) { if(type_register == nullptr) type_register = - std::make_unique>(); + std::make_unique>(); return (*type_register)[classname]; } - void Archive :: SetArchiveRegister(const std::string& classname, const ClassArchiveInfo& info) + void Archive :: SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info) { if(type_register == nullptr) type_register = - std::make_unique>(); + std::make_unique>(); (*type_register)[classname] = info; } bool Archive :: IsRegistered(const std::string& classname) { if(type_register == nullptr) type_register = - std::make_unique>(); + std::make_unique>(); return type_register->count(classname) != 0; } } // namespace ngcore diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 45fb31f5..6458c884 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -25,66 +25,72 @@ namespace ngcore void SetLibraryVersion(const std::string& library, const VersionInfo& version); class Archive; - NGCORE_API std::string demangle(const char* typeinfo); + NGCORE_API std::string Demangle(const char* typeinfo); - // create new pointer of type T if it is default constructible, else throw - template - T* constructIfPossible_impl(Rest... /*unused*/) - { throw std::runtime_error(std::string(demangle(typeid(T).name())) + " is not default constructible!"); } + namespace detail + { + // create new pointer of type T if it is default constructible, else throw + template + T* constructIfPossible_impl(Rest... /*unused*/) + { throw std::runtime_error(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } - template::value>::type> - T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT + template::value>::type> + T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT + + template + T* constructIfPossible() { return constructIfPossible_impl(int{}); } + + //Type trait to check if a class implements a 'void DoArchive(Archive&)' function + template + struct has_DoArchive + { + private: + template + static constexpr auto check(T2*) -> + typename std::is_same().DoArchive(std::declval())),void>::type; + template + static constexpr std::false_type check(...); + using type = decltype(check(nullptr)); // NOLINT + public: + NGCORE_API static constexpr bool value = type::value; + }; + + // Check if class is archivable + template + struct is_Archivable_struct + { + private: + template + static constexpr auto check(T2*) -> + typename std::is_same() & std::declval()),Archive&>::type; + template + static constexpr std::false_type check(...); + using type = decltype(check(nullptr)); // NOLINT + public: + NGCORE_API static constexpr bool value = type::value; + }; + + struct ClassArchiveInfo + { + // create new object of this type and return a void* pointer that is points to the location + // of the (base)class given by type_info + std::function creator; + // This caster takes a void* pointer to the type stored in this info and casts it to a + // void* pointer pointing to the (base)class type_info + std::function upcaster; + // This caster takes a void* pointer to the (base)class type_info and returns void* pointing + // to the type stored in this info + std::function downcaster; + }; + } // namespace detail template - T* constructIfPossible() { return constructIfPossible_impl(int{}); } - - //Type trait to check if a class implements a 'void DoArchive(Archive&)' function - template - struct has_DoArchive - { - private: - template - static constexpr auto check(T2*) -> - typename std::is_same().DoArchive(std::declval())),void>::type; - template - static constexpr std::false_type check(...); - using type = decltype(check(nullptr)); // NOLINT - public: - NGCORE_API static constexpr bool value = type::value; - }; - - // Check if class is archivable - template - struct is_Archivable - { - private: - template - static constexpr auto check(T2*) -> - typename std::is_same() & std::declval()),Archive&>::type; - template - static constexpr std::false_type check(...); - using type = decltype(check(nullptr)); // NOLINT - public: - NGCORE_API static constexpr bool value = type::value; - }; - - struct ClassArchiveInfo - { - // create new object of this type and return a void* pointer that is points to the location - // of the (base)class given by type_info - std::function creator; - // This caster takes a void* pointer to the type stored in this info and casts it to a - // void* pointer pointing to the (base)class type_info - std::function upcaster; - // This caster takes a void* pointer to the (base)class type_info and returns void* pointing - // to the type stored in this info - std::function downcaster; - }; + constexpr bool is_archivable = detail::is_Archivable_struct::value; // Base Archive class class NGCORE_API Archive { - bool is_output; + const bool is_output; // how many different shared_ptr/pointer have been (un)archived int shared_ptr_count, ptr_count; // maps for archived shared pointers and pointers @@ -103,11 +109,11 @@ namespace ngcore template friend class RegisterClassForArchive; - // Returns ClassArchiveInfo of demangled typeid - static const ClassArchiveInfo& GetArchiveRegister(const std::string& classname); - // Set ClassArchiveInfo for demangled typeid, this is done by creating an instance of + // Returns ClassArchiveInfo of Demangled typeid + static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname); + // Set ClassArchiveInfo for Demangled typeid, this is done by creating an instance of // RegisterClassForArchive - static void SetArchiveRegister(const std::string& classname, const ClassArchiveInfo& info); + static void SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info); static bool IsRegistered(const std::string& classname); public: Archive() = delete; @@ -121,8 +127,8 @@ namespace ngcore Archive& operator=(const Archive&) = delete; Archive& operator=(Archive&&) = delete; - bool Output () { return is_output; } - bool Input () { return !is_output; } + bool Output () const { return is_output; } + bool Input () const { return !is_output; } virtual const VersionInfo& getVersion(const std::string& library) = 0; // Pure virtual functions that have to be implemented by In-/OutArchive @@ -141,7 +147,7 @@ namespace ngcore template Archive& operator & (std::complex& c) { - if(is_output) + if(Output()) (*this) << c.real() << c.imag(); else { @@ -157,10 +163,10 @@ namespace ngcore Archive& operator & (std::vector& v) { size_t size; - if(is_output) + if(Output()) size = v.size(); (*this) & size; - if(!is_output) + if(Input()) v.resize(size); Do(&v[0], size); return (*this); @@ -168,7 +174,7 @@ namespace ngcore template Archive& operator& (std::map& map) { - if(is_output) + if(Output()) { (*this) << size_t(map.size()); for(auto& pair : map) @@ -190,7 +196,7 @@ namespace ngcore } // Archive arrays ===================================================== // this functions can be overloaded in Archive implementations for more efficiency - template ::value>::type> + template >::type> Archive & Do (T * data, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; // NOLINT @@ -216,7 +222,7 @@ namespace ngcore { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; // NOLINT // Archive a class implementing a (void DoArchive(Archive&)) method ======= - template::value>> + template::value>> Archive& operator & (T& val) { val.DoArchive(*this); return *this; @@ -237,11 +243,11 @@ namespace ngcore // Downcasting is only possible for our registered classes if(typeid(T) != typeid(*ptr)) { - if(!IsRegistered(demangle(typeid(*ptr).name()))) + if(!IsRegistered(Demangle(typeid(*ptr).name()))) throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + demangle(typeid(*ptr).name()) + + Demangle(typeid(*ptr).name()) + " not registered for archive"); - reg_ptr = GetArchiveRegister(demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); + reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); // if there was a true downcast we have to store more information if(reg_ptr != static_cast(ptr.get()) ) neededDowncast = true; @@ -255,14 +261,14 @@ namespace ngcore (*this) & neededDowncast & p; // if we did downcast we store the true type as well if(neededDowncast) - (*this) << demangle(typeid(*ptr).name()); + (*this) << Demangle(typeid(*ptr).name()); shared_ptr2nr[reg_ptr] = shared_ptr_count++; return *this; } // if found store the position and if it has to be downcasted and how (*this) << pos->second << neededDowncast; if(neededDowncast) - (*this) << demangle(typeid(*ptr).name()); + (*this) << Demangle(typeid(*ptr).name()); } else // Input { @@ -277,7 +283,7 @@ namespace ngcore // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it if (nr == -1) { - T* p; + T* p = nullptr; bool neededDowncast; (*this) & neededDowncast & p; ptr = std::shared_ptr(p); @@ -333,11 +339,11 @@ namespace ngcore void* reg_ptr = static_cast(p); if(typeid(T) != typeid(*p)) { - if(!IsRegistered(demangle(typeid(*p).name()))) + if(!IsRegistered(Demangle(typeid(*p).name()))) throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + demangle(typeid(*p).name()) + + Demangle(typeid(*p).name()) + " not registered for archive"); - reg_ptr = GetArchiveRegister(demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); + reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry @@ -351,18 +357,18 @@ namespace ngcore } else throw std::runtime_error(std::string("Archive error: Class ") + - demangle(typeid(*p).name()) + " does not provide a default constructor!"); + Demangle(typeid(*p).name()) + " does not provide a default constructor!"); else { // if a pointer to a base class is archived, the class hierarchy must be registered // to avoid compile time issues we allow this behaviour only for "our" classes that // implement a void DoArchive(Archive&) member function // To recreate the object we need to store the true type of it - if(!IsRegistered(demangle(typeid(*p).name()))) + if(!IsRegistered(Demangle(typeid(*p).name()))) throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + demangle(typeid(*p).name()) + + Demangle(typeid(*p).name()) + " not registered for archive"); - return (*this) << -3 << demangle(typeid(*p).name()) & (*p); + return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); } } else @@ -370,7 +376,7 @@ namespace ngcore (*this) & pos->second; bool downcasted = !(reg_ptr == static_cast(p) ); // store if the class has been downcasted and the name - (*this) << downcasted << demangle(typeid(*p).name()); + (*this) << downcasted << Demangle(typeid(*p).name()); } } else @@ -381,7 +387,7 @@ namespace ngcore p = nullptr; else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) { - p = constructIfPossible(); + p = detail::constructIfPossible(); nr2ptr.push_back(p); (*this) & *p; } @@ -457,7 +463,7 @@ namespace ngcore static void* tryUpcast(const std::type_info& ti, T* p) { try - { return GetArchiveRegister(demangle(typeid(B1).name())).upcaster(ti, static_cast(dynamic_cast(p))); } + { return GetArchiveRegister(Demangle(typeid(B1).name())).upcaster(ti, static_cast(dynamic_cast(p))); } catch(std::exception&) { return Caster::tryUpcast(ti, p); } } @@ -467,7 +473,7 @@ namespace ngcore if(typeid(B1) == ti) return dynamic_cast(static_cast(p)); try - { return GetArchiveRegister(demangle(typeid(B1).name())).downcaster(ti, static_cast(dynamic_cast(static_cast(p)))); } + { return GetArchiveRegister(Demangle(typeid(B1).name())).downcaster(ti, static_cast(dynamic_cast(static_cast(p)))); } catch(std::exception&) { return Caster::tryDowncast(ti, p); } } @@ -482,15 +488,15 @@ namespace ngcore { static_assert(all_of_tmpl::value...>, "Variadic template arguments must be base classes of T"); - ClassArchiveInfo info; + detail::ClassArchiveInfo info; info.creator = [this,&info](const std::type_info& ti) -> void* - { return typeid(T) == ti ? constructIfPossible() - : Archive::Caster::tryUpcast(ti, constructIfPossible()); }; + { return typeid(T) == ti ? detail::constructIfPossible() + : Archive::Caster::tryUpcast(ti, detail::constructIfPossible()); }; info.upcaster = [this](const std::type_info& ti, void* p) -> void* { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, static_cast(p)); }; info.downcaster = [this](const std::type_info& ti, void* p) -> void* { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; - Archive::SetArchiveRegister(std::string(demangle(typeid(T).name())),info); + Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info); } diff --git a/libsrc/general/array.hpp b/libsrc/general/array.hpp index bd2b569a..16bb6e78 100644 --- a/libsrc/general/array.hpp +++ b/libsrc/general/array.hpp @@ -403,7 +403,7 @@ namespace netgen // Only provide this function if T is archivable template - auto DoArchive(Archive& archive) -> typename std::enable_if::value, void>::type + auto DoArchive(Archive& archive) -> typename std::enable_if, void>::type { if(archive.Output()) archive << size; diff --git a/nglib/CMakeLists.txt b/nglib/CMakeLists.txt index 5429ffe6..ff8bd1d5 100644 --- a/nglib/CMakeLists.txt +++ b/nglib/CMakeLists.txt @@ -32,6 +32,8 @@ if(NOT WIN32) endif(USE_GUI) endif(NOT WIN32) +target_link_libraries(nglib PUBLIC ngcore) + target_link_libraries( nglib PRIVATE ${OCC_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${X11_Xmu_LIB} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} ${OCC_LIBRARIES} ) if(USE_OCC AND NOT WIN32) diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index a5ca80d5..50d3c0a7 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -108,7 +108,7 @@ void testSharedPointer(Archive& in, Archive& out) { SECTION("Same shared ptr") { - static_assert(has_DoArchive::value, ""); + static_assert(detail::has_DoArchive::value, ""); SharedPtrAndPtrHolder holder, holder2; holder.names.push_back(make_shared("name")); holder2.names = holder.names; // same shared ptr From d10d74753bb6eefd63f02fb750ab2a8ccc333536 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 12 Dec 2018 11:10:42 +0100 Subject: [PATCH 34/46] [gitlab-ci] Require python3-distutils for tests --- tests/dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dockerfile b/tests/dockerfile index 40152059..4567fdc4 100644 --- a/tests/dockerfile +++ b/tests/dockerfile @@ -1,5 +1,5 @@ FROM ubuntu:18.04 ENV DEBIAN_FRONTEND=noninteractive MAINTAINER Matthias Hochsteger -RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk clang-tidy +RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk clang-tidy python3-distutils ADD . /root/src/netgen From 814d75d1c7640866a2f8bb27b7b964a0897b51cb Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 12 Dec 2018 11:24:11 +0100 Subject: [PATCH 35/46] fix includes, fix naming convention --- libsrc/core/archive.cpp | 6 ------ libsrc/core/archive.hpp | 10 +++++----- tests/catch/archive.cpp | 4 ++-- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/libsrc/core/archive.cpp b/libsrc/core/archive.cpp index 5a526444..56bc5426 100644 --- a/libsrc/core/archive.cpp +++ b/libsrc/core/archive.cpp @@ -1,10 +1,4 @@ -#include // for function -#include // for runtime_error -#include // for declval, enable_if, false_type, is_co... -#include // for type_info -#include // for move, swap, pair - #include "archive.hpp" #ifndef WIN32 diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 6458c884..76dcbd5e 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -129,7 +129,7 @@ namespace ngcore bool Output () const { return is_output; } bool Input () const { return !is_output; } - virtual const VersionInfo& getVersion(const std::string& library) = 0; + virtual const VersionInfo& GetVersion(const std::string& library) = 0; // Pure virtual functions that have to be implemented by In-/OutArchive virtual Archive & operator & (double & d) = 0; @@ -525,7 +525,7 @@ namespace ngcore BinaryOutArchive& operator=(const BinaryOutArchive&) = delete; BinaryOutArchive& operator=(BinaryOutArchive&&) = delete; - const VersionInfo& getVersion(const std::string& library) override + const VersionInfo& GetVersion(const std::string& library) override { return GetLibraryVersions()[library]; } using Archive::operator&; @@ -601,7 +601,7 @@ namespace ngcore BinaryInArchive (const std::string& filename) : BinaryInArchive(std::make_shared(filename)) { ; } - const VersionInfo& getVersion(const std::string& library) override + const VersionInfo& GetVersion(const std::string& library) override { return vinfo[library]; } using Archive::operator&; @@ -669,7 +669,7 @@ namespace ngcore TextOutArchive (const std::string& filename) : TextOutArchive(std::make_shared(filename)) { } - const VersionInfo& getVersion(const std::string& library) override + const VersionInfo& GetVersion(const std::string& library) override { return GetLibraryVersions()[library]; } using Archive::operator&; @@ -725,7 +725,7 @@ namespace ngcore TextInArchive (const std::string& filename) : TextInArchive(std::make_shared(filename)) {} - const VersionInfo& getVersion(const std::string& library) override + const VersionInfo& GetVersion(const std::string& library) override { return vinfo[library]; } using Archive::operator&; diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index 50d3c0a7..ea5ac1dc 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -239,8 +239,8 @@ void testMultipleInheritance(Archive& in, Archive& out) void testLibraryVersion(Archive& in, Archive& out) { SetLibraryVersion("netgen","v6.2.1812"); - CHECK(in.getVersion("netgen") == "v6.2.1811"); - CHECK(out.getVersion("netgen") == "v6.2.1812"); + CHECK(in.GetVersion("netgen") == "v6.2.1811"); + CHECK(out.GetVersion("netgen") == "v6.2.1812"); } void testArchive(Archive& in, Archive& out) From 96e26565f25aa282b76d207d3680c63c918e20b5 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 12 Dec 2018 11:43:28 +0100 Subject: [PATCH 36/46] guideline checks as test --- .gitlab-ci.yml | 5 +++++ libsrc/core/archive.cpp | 2 +- tests/build.sh | 2 +- tests/build_guidelines.sh | 8 ++++++++ tests/dockerfile | 2 +- 5 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 tests/build_guidelines.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c7117fc7..74a6b10d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -140,6 +140,11 @@ test_ubuntu: <<: *ubuntu <<: *test_linux +# cpp guideline checks +test_guidelines: + stage: test + script: + - docker run netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh ############################################ # Deploy stage ############################################ diff --git a/libsrc/core/archive.cpp b/libsrc/core/archive.cpp index 56bc5426..2e6c32ae 100644 --- a/libsrc/core/archive.cpp +++ b/libsrc/core/archive.cpp @@ -24,7 +24,7 @@ namespace ngcore void SetLibraryVersion(const std::string& library, const VersionInfo& version) { library_versions[library] = version; } -#ifdef WIN +#ifdef WIN32 // windows does demangling in typeid(T).name() std::string Demangle(const char* typeinfo) { return typeinfo; } #else diff --git a/tests/build.sh b/tests/build.sh index d2727b2c..68aea3ad 100755 --- a/tests/build.sh +++ b/tests/build.sh @@ -1,6 +1,6 @@ cd mkdir -p build/netgen cd build/netgen -cmake ../../src/netgen -DUSE_CCACHE=ON -DENABLE_CPP_CORE_GUIDELINES_CHECK=ON +cmake ../../src/netgen -DUSE_CCACHE=ON make -j12 make install diff --git a/tests/build_guidelines.sh b/tests/build_guidelines.sh new file mode 100644 index 00000000..111b1cd0 --- /dev/null +++ b/tests/build_guidelines.sh @@ -0,0 +1,8 @@ +cd +mkdir -p build/netgen +cd build/netgen +cmake ../../src/netgen -DUSE_CCACHE=ON -DENABLE_CPP_CORE_GUIDELINES_CHECK=ON -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER=clang +make -j12 +make install + diff --git a/tests/dockerfile b/tests/dockerfile index 4567fdc4..ebed3dea 100644 --- a/tests/dockerfile +++ b/tests/dockerfile @@ -1,5 +1,5 @@ FROM ubuntu:18.04 ENV DEBIAN_FRONTEND=noninteractive MAINTAINER Matthias Hochsteger -RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk clang-tidy python3-distutils +RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk clang-tidy python3-distutils clang ADD . /root/src/netgen From f75563475bfe93a720c9ddcda8221d8cdc0d0af6 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 12 Dec 2018 13:07:18 +0100 Subject: [PATCH 37/46] remove multiple implemented function, always run guideline check --- .gitlab-ci.yml | 1 + libsrc/core/archive.cpp | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 74a6b10d..7f88a9bb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -145,6 +145,7 @@ test_guidelines: stage: test script: - docker run netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh + when: always ############################################ # Deploy stage ############################################ diff --git a/libsrc/core/archive.cpp b/libsrc/core/archive.cpp index 2e6c32ae..64789904 100644 --- a/libsrc/core/archive.cpp +++ b/libsrc/core/archive.cpp @@ -7,11 +7,6 @@ namespace ngcore { - void VersionInfo :: DoArchive(Archive& ar) - { - ar & mayor_ & minor_ & release & patch & git_hash; - } - // clang-tidy should ignore this static object static std::map library_versions; // NOLINT std::map& Archive :: GetLibraryVersions() From 47dd0eeead0260520d019ba834d5ce02f8774e61 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 12 Dec 2018 04:41:18 -0800 Subject: [PATCH 38/46] Fixes --- .gitlab-ci.yml | 2 +- external_dependencies/pybind11 | 2 +- libsrc/core/CMakeLists.txt | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7f88a9bb..1d14fa9a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -144,7 +144,7 @@ test_ubuntu: test_guidelines: stage: test script: - - docker run netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh + - docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh when: always ############################################ # Deploy stage diff --git a/external_dependencies/pybind11 b/external_dependencies/pybind11 index 2a150736..e0f3a766 160000 --- a/external_dependencies/pybind11 +++ b/external_dependencies/pybind11 @@ -1 +1 @@ -Subproject commit 2a150736601bb3113877bb673fb934bb60d46ec5 +Subproject commit e0f3a766e951ebbf2aadb31f41eb490de5bb607e diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 337bbfaa..9de7701f 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,7 +1,5 @@ +add_library(ngcore SHARED archive.cpp version.cpp) -add_library(ngcore archive.cpp version.cpp) - -set_target_properties(ngcore PROPERTIES POSITION_INDEPENDENT_CODE ON ) target_compile_definitions(ngcore PRIVATE -DNGCORE_EXPORTS) install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) From c9798fe16a2f50ec9f3c391f2a0b52c6b55cd279 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 12 Dec 2018 05:11:28 -0800 Subject: [PATCH 39/46] No need to dllexport template classes, fix forward declaration --- libsrc/core/archive.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 76dcbd5e..ac77db50 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -24,7 +24,7 @@ namespace ngcore const VersionInfo& GetLibraryVersion(const std::string& library); void SetLibraryVersion(const std::string& library, const VersionInfo& version); - class Archive; + class NGCORE_API Archive; NGCORE_API std::string Demangle(const char* typeinfo); namespace detail @@ -481,7 +481,7 @@ namespace ngcore }; template - class NGCORE_API RegisterClassForArchive + class RegisterClassForArchive { public: RegisterClassForArchive() From a722964823042926bf5e80083b20f22773adbc6c Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 12 Dec 2018 14:43:19 +0100 Subject: [PATCH 40/46] Fix gitlab-ci file --- .gitlab-ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1d14fa9a..85d70d56 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -45,9 +45,6 @@ stages: - pwd - ls - docker info - -.template_ubuntu: &ubuntu - <<: *ubuntu variables: UBUNTU_VERSION: "18.04" @@ -142,6 +139,7 @@ test_ubuntu: # cpp guideline checks test_guidelines: + <<: *ubuntu stage: test script: - docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh From 08275457c773105390ded8b92a11e31a6e76e083 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 12 Dec 2018 14:50:22 +0100 Subject: [PATCH 41/46] remove ngsolve import from pickle test, reverse pybind check --- external_dependencies/pybind11 | 2 +- tests/pytest/test_pickling.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/external_dependencies/pybind11 b/external_dependencies/pybind11 index e0f3a766..2a150736 160000 --- a/external_dependencies/pybind11 +++ b/external_dependencies/pybind11 @@ -1 +1 @@ -Subproject commit e0f3a766e951ebbf2aadb31f41eb490de5bb607e +Subproject commit 2a150736601bb3113877bb673fb934bb60d46ec5 diff --git a/tests/pytest/test_pickling.py b/tests/pytest/test_pickling.py index 7bbf1fa6..09e571a7 100644 --- a/tests/pytest/test_pickling.py +++ b/tests/pytest/test_pickling.py @@ -1,7 +1,6 @@ import netgen.csg as csg import pickle, numpy -from ngsolve import Draw, Mesh def test_pickle_csg(): geo = csg.CSGeometry() From fe2a5b382d44830fec17ec1084dbd92538d06c14 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 12 Dec 2018 15:35:19 +0100 Subject: [PATCH 42/46] fix auto use --- libsrc/core/archive.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index ac77db50..29504ec0 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -336,7 +336,7 @@ namespace ngcore // if the pointer is null store -2 if (!p) return (*this) << -2; - void* reg_ptr = static_cast(p); + auto reg_ptr = static_cast(p); if(typeid(T) != typeid(*p)) { if(!IsRegistered(Demangle(typeid(*p).name()))) From 5a9e913172066f6cec70f2f3acf3af66576ccb67 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 12 Dec 2018 16:57:48 +0100 Subject: [PATCH 43/46] fix downcaster for archive --- libsrc/core/archive.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 29504ec0..620941c9 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -463,7 +463,8 @@ namespace ngcore static void* tryUpcast(const std::type_info& ti, T* p) { try - { return GetArchiveRegister(Demangle(typeid(B1).name())).upcaster(ti, static_cast(dynamic_cast(p))); } + { return GetArchiveRegister(Demangle(typeid(B1).name())). + upcaster(ti, static_cast(dynamic_cast(p))); } catch(std::exception&) { return Caster::tryUpcast(ti, p); } } @@ -473,9 +474,14 @@ namespace ngcore if(typeid(B1) == ti) return dynamic_cast(static_cast(p)); try - { return GetArchiveRegister(Demangle(typeid(B1).name())).downcaster(ti, static_cast(dynamic_cast(static_cast(p)))); } + { + return dynamic_cast(static_cast(GetArchiveRegister(Demangle(typeid(B1).name())). + downcaster(ti, p))); + } catch(std::exception&) - { return Caster::tryDowncast(ti, p); } + { + return Caster::tryDowncast(ti, p); + } } }; }; From 835b2703f48821df84a5aa8a8b2f717b47e76281 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 12 Dec 2018 17:18:52 +0100 Subject: [PATCH 44/46] Remove version.cpp --- libsrc/core/CMakeLists.txt | 2 +- libsrc/core/archive.hpp | 14 +++++++++++++- libsrc/core/version.cpp | 11 ----------- libsrc/core/version.hpp | 3 --- 4 files changed, 14 insertions(+), 16 deletions(-) delete mode 100644 libsrc/core/version.cpp diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 9de7701f..e7fe7240 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(ngcore SHARED archive.cpp version.cpp) +add_library(ngcore SHARED archive.cpp) target_compile_definitions(ngcore PRIVATE -DNGCORE_EXPORTS) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 620941c9..1d3809b7 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -142,6 +142,18 @@ namespace ngcore virtual Archive & operator & (std::string & str) = 0; virtual Archive & operator & (char *& str) = 0; + virtual Archive & operator & (VersionInfo & version) + { + if(Output()) + (*this) << version.to_string(); + else + { + std::string s; + (*this) & s; + version = VersionInfo(s); + } + return *this; + } // Archive std classes ================================================ template @@ -182,7 +194,7 @@ namespace ngcore } else { - size_t size; + size_t size = 0; (*this) & size; T1 key; T2 val; for(size_t i = 0; i < size; i++) diff --git a/libsrc/core/version.cpp b/libsrc/core/version.cpp deleted file mode 100644 index 7f6bac69..00000000 --- a/libsrc/core/version.cpp +++ /dev/null @@ -1,11 +0,0 @@ - -#include "archive.hpp" -#include "version.hpp" - -namespace ngcore -{ - void VersionInfo :: DoArchive(Archive& ar) - { - ar & mayor_ & minor_ & release & patch & git_hash; - } -} // namespace ngcore diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp index ab14d74a..69598716 100644 --- a/libsrc/core/version.hpp +++ b/libsrc/core/version.hpp @@ -8,7 +8,6 @@ namespace ngcore { - class Archive; class VersionInfo { private: @@ -83,8 +82,6 @@ namespace ngcore bool operator >(const VersionInfo& other) const { return other < (*this); } bool operator <=(const VersionInfo& other) const { return !((*this) > other); } bool operator >=(const VersionInfo& other) const { return !((*this) < other); } - - void DoArchive(Archive& ar); }; } // namespace ngcore From c48663d7086bacdebd2b472e46f3f51d39827bed Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 12 Dec 2018 17:45:06 +0100 Subject: [PATCH 45/46] Some dll header --- libsrc/core/archive.hpp | 39 ++++++++++++++++++------------------- libsrc/core/type_traits.hpp | 10 +++++++--- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 1d3809b7..c69fa293 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -21,11 +21,11 @@ namespace ngcore { // Libraries using this archive can store their version here to implement backwards compatibility - const VersionInfo& GetLibraryVersion(const std::string& library); - void SetLibraryVersion(const std::string& library, const VersionInfo& version); + NGCORE_API const VersionInfo& GetLibraryVersion(const std::string& library); + NGCORE_API void SetLibraryVersion(const std::string& library, const VersionInfo& version); + NGCORE_API std::string Demangle(const char* typeinfo); class NGCORE_API Archive; - NGCORE_API std::string Demangle(const char* typeinfo); namespace detail { @@ -99,22 +99,6 @@ namespace ngcore std::vector> nr2shared_ptr; std::vector nr2ptr; - // Helper class for up-/downcasting - template - struct Caster - { - static void* tryUpcast(const std::type_info& ti, T* p); - static void* tryDowncast(const std::type_info& ti, void* p); - }; - template - friend class RegisterClassForArchive; - - // Returns ClassArchiveInfo of Demangled typeid - static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname); - // Set ClassArchiveInfo for Demangled typeid, this is done by creating an instance of - // RegisterClassForArchive - static void SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info); - static bool IsRegistered(const std::string& classname); public: Archive() = delete; Archive(const Archive&) = delete; @@ -455,7 +439,22 @@ namespace ngcore protected: static std::map& GetLibraryVersions(); + private: + template + friend class RegisterClassForArchive; + + // Returns ClassArchiveInfo of Demangled typeid + static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname); + // Set ClassArchiveInfo for Demangled typeid, this is done by creating an instance of + // RegisterClassForArchive + static void SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info); + static bool IsRegistered(const std::string& classname); + + // Helper class for up-/downcasting + template + struct Caster{}; + template struct Caster { @@ -504,7 +503,7 @@ namespace ngcore public: RegisterClassForArchive() { - static_assert(all_of_tmpl::value...>, + static_assert(detail::all_of_tmpl::value...>, "Variadic template arguments must be base classes of T"); detail::ClassArchiveInfo info; info.creator = [this,&info](const std::type_info& ti) -> void* diff --git a/libsrc/core/type_traits.hpp b/libsrc/core/type_traits.hpp index 36315e7a..0d558b05 100644 --- a/libsrc/core/type_traits.hpp +++ b/libsrc/core/type_traits.hpp @@ -5,9 +5,13 @@ namespace ngcore { - template struct _BoolArray{}; - template - constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(vals || true)...>>::value; // NOLINT + namespace detail + { + template struct _BoolArray{}; + + template + constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(vals || true)...>>::value; // NOLINT + } // namespace detail } // namespace ngcore #endif // NETGEN_LIBSRC_CORE_TYPE_TRAITS_HPP From d59b30025bfff96a7bafdbd2428f1aa0f61956c7 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Thu, 13 Dec 2018 11:10:12 +0100 Subject: [PATCH 46/46] consistent header guards --- libsrc/core/type_traits.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsrc/core/type_traits.hpp b/libsrc/core/type_traits.hpp index 0d558b05..3e7cd4b4 100644 --- a/libsrc/core/type_traits.hpp +++ b/libsrc/core/type_traits.hpp @@ -1,5 +1,5 @@ -#ifndef NETGEN_LIBSRC_CORE_TYPE_TRAITS_HPP -#define NETGEN_LIBSRC_CORE_TYPE_TRAITS_HPP +#ifndef NETGEN_CORE_TYPE_TRAITS_HPP +#define NETGEN_CORE_TYPE_TRAITS_HPP #include @@ -14,4 +14,4 @@ namespace ngcore } // namespace detail } // namespace ngcore -#endif // NETGEN_LIBSRC_CORE_TYPE_TRAITS_HPP +#endif // NETGEN_CORE_TYPE_TRAITS_HPP