Merge branch 'hasharchive' into 'master'

Hasharchive

See merge request jschoeberl/netgen!334
This commit is contained in:
Joachim Schöberl 2020-08-29 15:16:21 +00:00
commit c0a3cd0ff9
3 changed files with 91 additions and 20 deletions

View File

@ -910,6 +910,54 @@ namespace ngcore
}
};
// HashArchive =================================================================
// This class enables to easily create hashes for archivable objects by xoring
// threw its data
class NGCORE_API HashArchive : public Archive
{
size_t hash_value;
char* h;
int offset;
public:
HashArchive() : Archive(true)
{ h = (char*)&hash_value; }
using Archive::operator&;
Archive & operator & (double & d) override { return ApplyHash(d); }
Archive & operator & (int & i) override { return ApplyHash(i); }
Archive & operator & (short & i) override { return ApplyHash(i); }
Archive & operator & (long & i) override { return ApplyHash(i); }
Archive & operator & (size_t & i) override { return ApplyHash(i); }
Archive & operator & (unsigned char & i) override { return ApplyHash(i); }
Archive & operator & (bool & b) override { return ApplyHash(b); }
Archive & operator & (std::string & str) override
{ for(auto c : str) ApplyHash(c); return *this; }
Archive & operator & (char *& str) override
{ char* s = str; while(*s != '\0') ApplyHash(*(s++)); return *this; }
// HashArchive can be used in const context
template<typename T>
Archive & operator& (const T& val) const
{ return (*this) & const_cast<T&>(val); }
size_t GetHash() const { return hash_value; }
private:
template<typename T>
Archive& ApplyHash(T val)
{
auto n = sizeof(T);
char* pval = (char*)&val;
for(int i = 0; i < n; i++)
{
h[offset++] ^= pval[i];
offset %= 8;
}
return *this;
}
};
} // namespace ngcore
#endif // NETGEN_CORE_ARCHIVE_HPP

View File

@ -83,6 +83,18 @@ namespace ngcore
return *this;
}
bool BitArray :: operator==(const BitArray& other) const
{
if(size != other.Size())
return false;
for(auto i : Range(size/CHAR_BIT))
if(data[i] != other.data[i])
return false;
for(auto i : Range(size%CHAR_BIT))
if(Test(i + size * (size/CHAR_BIT)) != other.Test(i + size * (size/CHAR_BIT)))
return false;
return true;
}
BitArray & BitArray :: operator= (const BitArray & ba2)
{
@ -115,29 +127,39 @@ namespace ngcore
return cnt;
}
Archive & operator & (Archive & archive, BitArray & ba)
void BitArray :: DoArchive(Archive& archive)
{
if(archive.GetVersion("netgen") >= "v6.2.2007-62")
{
archive.NeedsVersion("netgen", "v6.2.2007-62");
auto size = Size();
archive & size;
if(archive.Input())
SetSize(size);
archive.Do(data, size/CHAR_BIT+1);
}
else
{
if (archive.Output())
{
archive << ba.Size();
for (size_t i = 0; i < ba.Size(); i++)
archive << ba[i];
throw Exception("should not get here");
archive << Size();
for (size_t i = 0; i < Size(); i++)
archive << (*this)[i];
}
else
{
size_t size;
archive & size;
ba.SetSize (size);
ba.Clear();
SetSize (size);
Clear();
for (size_t i = 0; i < size; i++)
{
bool b;
archive & b;
if (b) ba.SetBit(i);
if (b) SetBit(i);
}
}
return archive;
}
}
}
} // namespace ngcore

View File

@ -131,6 +131,7 @@ public:
return Test(i);
}
NGCORE_API bool operator==(const BitArray& other) const;
/// invert all bits
NGCORE_API BitArray & Invert ();
@ -145,6 +146,9 @@ public:
NGCORE_API BitArray & operator= (const BitArray & ba2);
NGCORE_API size_t NumSet () const;
NGCORE_API void DoArchive(Archive& archive);
private:
///
unsigned char Mask (size_t i) const
@ -190,11 +194,8 @@ private:
return res;
}
NGCORE_API std::ostream & operator<<(std::ostream & s, const BitArray & ba);
NGCORE_API Archive & operator & (Archive & archive, BitArray & ba);
} // namespace ngcore
#endif // NETGEN_CORE_BITARRAY