version checks for archive, fix archive of empty string

This commit is contained in:
Christopher Lackner 2018-12-05 14:20:24 +01:00
parent a1847ec05f
commit 292dbcf5a0
10 changed files with 219 additions and 23 deletions

View File

@ -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
)

View File

@ -6,16 +6,22 @@ namespace ngcore
// BinaryOutArchive ======================================================================
class BinaryOutArchive : public Archive
{
std::shared_ptr<std::ostream> fout;
size_t ptr = 0;
enum { BUFFERSIZE = 1024 };
char buffer[BUFFERSIZE];
std::shared_ptr<std::ostream> fout;
public:
BinaryOutArchive (std::shared_ptr<std::ostream> afout) : Archive(true), fout(afout) { ; }
BinaryOutArchive (std::string filename)
BinaryOutArchive(std::shared_ptr<std::ostream> afout) : Archive(true), fout(afout)
{
(*this) & GetLibraryVersions();
}
BinaryOutArchive(std::string filename)
: BinaryOutArchive(std::make_shared<std::ofstream>(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<std::string, VersionInfo> vinfo;
std::shared_ptr<std::istream> fin;
public:
BinaryInArchive (std::shared_ptr<std::istream> afin) : Archive(false), fin(afin) { ; }
BinaryInArchive (std::shared_ptr<std::istream> afin) : Archive(false), fin(afin)
{
(*this) & vinfo;
}
BinaryInArchive (std::string filename)
: BinaryInArchive(std::make_shared<std::ifstream>(filename)) {}
: BinaryInArchive(std::make_shared<std::ifstream>(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<std::ostream> fout;
public:
TextOutArchive (std::shared_ptr<std::ostream> afout) : Archive(true), fout(afout) { }
TextOutArchive (std::shared_ptr<std::ostream> afout) : Archive(true), fout(afout)
{
(*this) & GetLibraryVersions();
}
TextOutArchive (std::string filename) :
TextOutArchive(std::make_shared<std::ofstream>(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<std::string, VersionInfo> vinfo;
std::shared_ptr<std::istream> fin;
public:
TextInArchive (std::shared_ptr<std::istream> afin) : Archive(false), fin(afin) { ; }
TextInArchive (std::shared_ptr<std::istream> afin) : Archive(false), fin(afin)
{
(*this) & vinfo;
}
TextInArchive (std::string filename)
: TextInArchive(std::make_shared<std::ifstream>(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;
}

View File

@ -7,6 +7,11 @@
namespace ngcore
{
std::map<std::string, VersionInfo>& GetLibraryVersions()
{
static std::map<std::string, VersionInfo> library_versions;
return library_versions;
}
#ifdef WIN
// windows does demangling in typeid(T).name()
std::string demangle(const char* typeinfo) { return typeinfo; }

View File

@ -3,6 +3,10 @@
namespace ngcore
{
class VersionInfo;
// Libraries using this archive can store their version here to implement backwards compatibility
std::map<std::string, VersionInfo>& 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<typename T1, typename T2>
Archive& operator& (std::map<T1, T2>& 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 <typename T>

View File

@ -6,6 +6,7 @@
#include <string>
#include <vector>
#include <map>
#include <iterator>
#include <type_traits>
#include <functional>
#include <stdexcept>
@ -15,6 +16,8 @@
#include <complex>
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

84
libsrc/core/version.hpp Normal file
View File

@ -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;
}
};
}

View File

@ -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<stringstream>();
BinaryOutArchive archive(ss);
archive & self;
return py::make_tuple(ss->str());
},
[](py::tuple state)
{
auto geo = make_shared<CSGeometry>();
auto val = py::cast<string>(state[0]);
cout << "unpickle = " << endl << val << endl;
stringstream ss(py::cast<string>(state[0]));
// geo->Load(ss);
// geo->FindIdenticSurfaces(1e-8 * geo->MaxSize());
auto ss = make_shared<stringstream> (py::cast<string>(state[0]));
BinaryInArchive archive(ss);
archive & (*geo);
return geo;
}))
.def("Save", FunctionPointer([] (CSGeometry & self, string filename)

View File

@ -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)

View File

@ -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<stringstream>();
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<stringstream>();
TextOutArchive out(stream);
TextInArchive in(stream);

19
tests/catch/version.cpp Normal file
View File

@ -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");
}