util.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2020, The University of Memphis
4  *
5  * This file is part of PSync.
6  * See AUTHORS.md for complete list of PSync authors and contributors.
7  *
8  * PSync is free software: you can redistribute it and/or modify it under the terms
9  * of the GNU Lesser General Public License as published by the Free Software Foundation,
10  * either version 3 of the License, or (at your option) any later version.
11  *
12  * PSync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  * PURPOSE. See the GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License along with
17  * PSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * murmurHash3 was written by Austin Appleby, and is placed in the public
20  * domain. The author hereby disclaims copyright to this source code.
21  * https://github.com/aappleby/smhasher/blob/master/src/murmurHash3.cpp
22  **/
23 
24 #include "PSync/detail/util.hpp"
25 #include "PSync/detail/config.hpp"
26 
27 #include <ndn-cxx/encoding/buffer-stream.hpp>
28 #include <ndn-cxx/util/backports.hpp>
29 #include <ndn-cxx/util/exception.hpp>
30 
31 #include <boost/iostreams/device/array.hpp>
32 #include <boost/iostreams/filtering_stream.hpp>
33 #ifdef PSYNC_HAVE_ZLIB
34  #include <boost/iostreams/filter/zlib.hpp>
35 #endif
36 #ifdef PSYNC_HAVE_GZIP
37  #include <boost/iostreams/filter/gzip.hpp>
38 #endif
39 #ifdef PSYNC_HAVE_BZIP2
40  #include <boost/iostreams/filter/bzip2.hpp>
41 #endif
42 #ifdef PSYNC_HAVE_LZMA
43  #include <boost/iostreams/filter/lzma.hpp>
44 #endif
45 #ifdef PSYNC_HAVE_ZSTD
46  #include <boost/iostreams/filter/zstd.hpp>
47 #endif
48 #include <boost/iostreams/copy.hpp>
49 
50 namespace psync {
51 
52 namespace bio = boost::iostreams;
53 
54 static uint32_t
55 ROTL32 ( uint32_t x, int8_t r )
56 {
57  return (x << r) | (x >> (32 - r));
58 }
59 
60 uint32_t
61 murmurHash3(uint32_t nHashSeed, const std::vector<unsigned char>& vDataToHash)
62 {
63  uint32_t h1 = nHashSeed;
64  const uint32_t c1 = 0xcc9e2d51;
65  const uint32_t c2 = 0x1b873593;
66 
67  const size_t nblocks = vDataToHash.size() / 4;
68 
69  //----------
70  // body
71  const uint32_t * blocks = (const uint32_t *)(&vDataToHash[0] + nblocks*4);
72 
73  for (size_t i = -nblocks; i; i++) {
74  uint32_t k1 = blocks[i];
75 
76  k1 *= c1;
77  k1 = ROTL32(k1,15);
78  k1 *= c2;
79 
80  h1 ^= k1;
81  h1 = ROTL32(h1,13);
82  h1 = h1*5+0xe6546b64;
83  }
84 
85  //----------
86  // tail
87  const uint8_t * tail = (const uint8_t*)(&vDataToHash[0] + nblocks*4);
88 
89  uint32_t k1 = 0;
90 
91  switch (vDataToHash.size() & 3) {
92  case 3:
93  k1 ^= tail[2] << 16;
94  NDN_CXX_FALLTHROUGH;
95 
96  case 2:
97  k1 ^= tail[1] << 8;
98  NDN_CXX_FALLTHROUGH;
99 
100  case 1:
101  k1 ^= tail[0];
102  k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
103  }
104 
105  //----------
106  // finalization
107  h1 ^= vDataToHash.size();
108  h1 ^= h1 >> 16;
109  h1 *= 0x85ebca6b;
110  h1 ^= h1 >> 13;
111  h1 *= 0xc2b2ae35;
112  h1 ^= h1 >> 16;
113 
114  return h1;
115 }
116 
117 uint32_t
118 murmurHash3(uint32_t nHashSeed, const std::string& str)
119 {
120  return murmurHash3(nHashSeed, std::vector<unsigned char>(str.begin(), str.end()));
121 }
122 
123 uint32_t
124 murmurHash3(uint32_t nHashSeed, uint32_t value)
125 {
126  return murmurHash3(nHashSeed,
127  std::vector<unsigned char>((unsigned char*)&value,
128  (unsigned char*)&value + sizeof(uint32_t)));
129 }
130 
131 std::shared_ptr<ndn::Buffer>
132 compress(CompressionScheme scheme, const uint8_t* buffer, size_t bufferSize)
133 {
134  ndn::OBufferStream out;
135  bio::filtering_streambuf<bio::input> in;
136  switch (scheme) {
138 #ifdef PSYNC_HAVE_ZLIB
139  in.push(bio::zlib_compressor(bio::zlib::best_compression));
140 #else
141  NDN_THROW(Error("ZLIB compression not supported!"));
142 #endif
143  break;
144 
146 #ifdef PSYNC_HAVE_GZIP
147  in.push(bio::gzip_compressor(bio::gzip::best_compression));
148 #else
149  NDN_THROW(Error("GZIP compression not supported!"));
150 #endif
151  break;
152 
154 #ifdef PSYNC_HAVE_BZIP2
155  in.push(bio::bzip2_compressor());
156 #else
157  NDN_THROW(Error("BZIP2 compression not supported!"));
158 #endif
159  break;
160 
162 #ifdef PSYNC_HAVE_LZMA
163  in.push(bio::lzma_compressor(bio::lzma::best_compression));
164 #else
165  NDN_THROW(Error("LZMA compression not supported!"));
166 #endif
167  break;
168 
170 #ifdef PSYNC_HAVE_ZSTD
171  in.push(bio::zstd_compressor(bio::zstd::best_compression));
172 #else
173  NDN_THROW(Error("ZSTD compression not supported!"));
174 #endif
175  break;
176 
178  break;
179  }
180  in.push(bio::array_source(reinterpret_cast<const char*>(buffer), bufferSize));
181  bio::copy(in, out);
182 
183  return out.buf();
184 }
185 
186 std::shared_ptr<ndn::Buffer>
187 decompress(CompressionScheme scheme, const uint8_t* buffer, size_t bufferSize)
188 {
189  ndn::OBufferStream out;
190  bio::filtering_streambuf<bio::input> in;
191  switch (scheme) {
193 #ifdef PSYNC_HAVE_ZLIB
194  in.push(bio::zlib_decompressor());
195 #else
196  NDN_THROW(Error("ZLIB decompression not supported!"));
197 #endif
198  break;
199 
201 #ifdef PSYNC_HAVE_GZIP
202  in.push(bio::gzip_decompressor());
203 #else
204  NDN_THROW(Error("GZIP compression not supported!"));
205 #endif
206  break;
207 
209 #ifdef PSYNC_HAVE_BZIP2
210  in.push(bio::bzip2_decompressor());
211 #else
212  NDN_THROW(Error("BZIP2 compression not supported!"));
213 #endif
214  break;
215 
217 #ifdef PSYNC_HAVE_LZMA
218  in.push(bio::lzma_decompressor());
219 #else
220  NDN_THROW(Error("LZMA compression not supported!"));
221 #endif
222  break;
223 
225 #ifdef PSYNC_HAVE_ZSTD
226  in.push(bio::zstd_decompressor());
227 #else
228  NDN_THROW(Error("ZSTD compression not supported!"));
229 #endif
230  break;
231 
233  break;
234  }
235  in.push(bio::array_source(reinterpret_cast<const char*>(buffer), bufferSize));
236  bio::copy(in, out);
237 
238  return out.buf();
239 }
240 
241 } // namespace psync
uint32_t murmurHash3(uint32_t nHashSeed, const std::vector< unsigned char > &vDataToHash)
Definition: util.cpp:61
std::shared_ptr< ndn::Buffer > decompress(CompressionScheme scheme, const uint8_t *buffer, size_t bufferSize)
Definition: util.cpp:187
CompressionScheme
Definition: util.hpp:51
std::shared_ptr< ndn::Buffer > compress(CompressionScheme scheme, const uint8_t *buffer, size_t bufferSize)
Definition: util.cpp:132
static uint32_t ROTL32(uint32_t x, int8_t r)
Definition: util.cpp:55