Files
PSync/PSync/detail/util.cpp
T
Davide Pesavento 03426efa2c Minor code cleanups
Change-Id: I2b67216754ba30563a65a2697e6801e363986da1
2022-09-25 14:06:26 -04:00

242 lines
5.9 KiB
C++

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, The University of Memphis
*
* This file is part of PSync.
* See AUTHORS.md for complete list of PSync authors and contributors.
*
* PSync is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* PSync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* PSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* murmurHash3 was written by Austin Appleby, and is placed in the public
* domain. The author hereby disclaims copyright to this source code.
* https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp
*/
#include "PSync/detail/util.hpp"
#include <ndn-cxx/encoding/buffer-stream.hpp>
#include <ndn-cxx/util/backports.hpp>
#include <ndn-cxx/util/exception.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#ifdef PSYNC_HAVE_ZLIB
#include <boost/iostreams/filter/zlib.hpp>
#endif
#ifdef PSYNC_HAVE_GZIP
#include <boost/iostreams/filter/gzip.hpp>
#endif
#ifdef PSYNC_HAVE_BZIP2
#include <boost/iostreams/filter/bzip2.hpp>
#endif
#ifdef PSYNC_HAVE_LZMA
#include <boost/iostreams/filter/lzma.hpp>
#endif
#ifdef PSYNC_HAVE_ZSTD
#include <boost/iostreams/filter/zstd.hpp>
#endif
namespace psync::detail {
static inline uint32_t
ROTL32(uint32_t x, int8_t r)
{
return (x << r) | (x >> (32 - r));
}
uint32_t
murmurHash3(const void* key, size_t len, uint32_t seed)
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 4;
uint32_t h1 = seed;
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
//----------
// body
const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
for (int i = -nblocks; i; i++)
{
uint32_t k1 = blocks[i];
k1 *= c1;
k1 = ROTL32(k1,15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32(h1,13);
h1 = h1*5+0xe6546b64;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
uint32_t k1 = 0;
switch (len & 3)
{
case 3: k1 ^= tail[2] << 16;
[[fallthrough]];
case 2: k1 ^= tail[1] << 8;
[[fallthrough]];
case 1: k1 ^= tail[0];
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
}
//----------
// finalization
h1 ^= len;
h1 ^= h1 >> 16;
h1 *= 0x85ebca6b;
h1 ^= h1 >> 13;
h1 *= 0xc2b2ae35;
h1 ^= h1 >> 16;
return h1;
}
uint32_t
murmurHash3(uint32_t seed, const ndn::Name& name)
{
const auto& wire = name.wireEncode();
return murmurHash3(wire.value(), wire.value_size(), seed);
}
std::shared_ptr<ndn::Buffer>
compress(CompressionScheme scheme, ndn::span<const uint8_t> buffer)
{
namespace bio = boost::iostreams;
bio::filtering_istreambuf in;
switch (scheme) {
case CompressionScheme::NONE:
break;
case CompressionScheme::ZLIB:
#ifdef PSYNC_HAVE_ZLIB
in.push(bio::zlib_compressor(bio::zlib::best_compression));
break;
#else
NDN_THROW(CompressionError("ZLIB compression not supported!"));
#endif
case CompressionScheme::GZIP:
#ifdef PSYNC_HAVE_GZIP
in.push(bio::gzip_compressor(bio::gzip::best_compression));
break;
#else
NDN_THROW(CompressionError("GZIP compression not supported!"));
#endif
case CompressionScheme::BZIP2:
#ifdef PSYNC_HAVE_BZIP2
in.push(bio::bzip2_compressor());
break;
#else
NDN_THROW(CompressionError("BZIP2 compression not supported!"));
#endif
case CompressionScheme::LZMA:
#ifdef PSYNC_HAVE_LZMA
in.push(bio::lzma_compressor(bio::lzma::best_compression));
break;
#else
NDN_THROW(CompressionError("LZMA compression not supported!"));
#endif
case CompressionScheme::ZSTD:
#ifdef PSYNC_HAVE_ZSTD
in.push(bio::zstd_compressor(bio::zstd::best_compression));
break;
#else
NDN_THROW(CompressionError("ZSTD compression not supported!"));
#endif
}
in.push(bio::array_source(reinterpret_cast<const char*>(buffer.data()), buffer.size()));
ndn::OBufferStream out;
bio::copy(in, out);
return out.buf();
}
std::shared_ptr<ndn::Buffer>
decompress(CompressionScheme scheme, ndn::span<const uint8_t> buffer)
{
namespace bio = boost::iostreams;
bio::filtering_istreambuf in;
switch (scheme) {
case CompressionScheme::NONE:
break;
case CompressionScheme::ZLIB:
#ifdef PSYNC_HAVE_ZLIB
in.push(bio::zlib_decompressor());
break;
#else
NDN_THROW(CompressionError("ZLIB decompression not supported!"));
#endif
case CompressionScheme::GZIP:
#ifdef PSYNC_HAVE_GZIP
in.push(bio::gzip_decompressor());
break;
#else
NDN_THROW(CompressionError("GZIP compression not supported!"));
#endif
case CompressionScheme::BZIP2:
#ifdef PSYNC_HAVE_BZIP2
in.push(bio::bzip2_decompressor());
break;
#else
NDN_THROW(CompressionError("BZIP2 compression not supported!"));
#endif
case CompressionScheme::LZMA:
#ifdef PSYNC_HAVE_LZMA
in.push(bio::lzma_decompressor());
break;
#else
NDN_THROW(CompressionError("LZMA compression not supported!"));
#endif
case CompressionScheme::ZSTD:
#ifdef PSYNC_HAVE_ZSTD
in.push(bio::zstd_decompressor());
break;
#else
NDN_THROW(CompressionError("ZSTD compression not supported!"));
#endif
}
in.push(bio::array_source(reinterpret_cast<const char*>(buffer.data()), buffer.size()));
ndn::OBufferStream out;
bio::copy(in, out);
return out.buf();
}
} // namespace psync::detail