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-2022, 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 
26 #include <ndn-cxx/encoding/buffer-stream.hpp>
27 #include <ndn-cxx/util/backports.hpp>
28 #include <ndn-cxx/util/exception.hpp>
29 
30 #include <boost/iostreams/copy.hpp>
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 
49 namespace psync::detail {
50 
51 static inline uint32_t
52 ROTL32(uint32_t x, int8_t r)
53 {
54  return (x << r) | (x >> (32 - r));
55 }
56 
57 uint32_t
58 murmurHash3(const void* key, size_t len, uint32_t seed)
59 {
60  const uint8_t * data = (const uint8_t*)key;
61  const int nblocks = len / 4;
62 
63  uint32_t h1 = seed;
64 
65  const uint32_t c1 = 0xcc9e2d51;
66  const uint32_t c2 = 0x1b873593;
67 
68  //----------
69  // body
70 
71  const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
72 
73  for (int i = -nblocks; i; i++)
74  {
75  uint32_t k1 = blocks[i];
76 
77  k1 *= c1;
78  k1 = ROTL32(k1,15);
79  k1 *= c2;
80 
81  h1 ^= k1;
82  h1 = ROTL32(h1,13);
83  h1 = h1*5+0xe6546b64;
84  }
85 
86  //----------
87  // tail
88 
89  const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
90 
91  uint32_t k1 = 0;
92 
93  switch (len & 3)
94  {
95  case 3: k1 ^= tail[2] << 16;
96  [[fallthrough]];
97  case 2: k1 ^= tail[1] << 8;
98  [[fallthrough]];
99  case 1: k1 ^= tail[0];
100  k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
101  }
102 
103  //----------
104  // finalization
105 
106  h1 ^= len;
107  h1 ^= h1 >> 16;
108  h1 *= 0x85ebca6b;
109  h1 ^= h1 >> 13;
110  h1 *= 0xc2b2ae35;
111  h1 ^= h1 >> 16;
112 
113  return h1;
114 }
115 
116 uint32_t
117 murmurHash3(uint32_t seed, const ndn::Name& name)
118 {
119  const auto& wire = name.wireEncode();
120  return murmurHash3(wire.value(), wire.value_size(), seed);
121 }
122 
123 std::shared_ptr<ndn::Buffer>
124 compress(CompressionScheme scheme, ndn::span<const uint8_t> buffer)
125 {
126  namespace bio = boost::iostreams;
127 
128  bio::filtering_istreambuf in;
129 
130  switch (scheme) {
132  break;
133 
135 #ifdef PSYNC_HAVE_ZLIB
136  in.push(bio::zlib_compressor(bio::zlib::best_compression));
137  break;
138 #else
139  NDN_THROW(CompressionError("ZLIB compression not supported!"));
140 #endif
141 
143 #ifdef PSYNC_HAVE_GZIP
144  in.push(bio::gzip_compressor(bio::gzip::best_compression));
145  break;
146 #else
147  NDN_THROW(CompressionError("GZIP compression not supported!"));
148 #endif
149 
151 #ifdef PSYNC_HAVE_BZIP2
152  in.push(bio::bzip2_compressor());
153  break;
154 #else
155  NDN_THROW(CompressionError("BZIP2 compression not supported!"));
156 #endif
157 
159 #ifdef PSYNC_HAVE_LZMA
160  in.push(bio::lzma_compressor(bio::lzma::best_compression));
161  break;
162 #else
163  NDN_THROW(CompressionError("LZMA compression not supported!"));
164 #endif
165 
167 #ifdef PSYNC_HAVE_ZSTD
168  in.push(bio::zstd_compressor(bio::zstd::best_compression));
169  break;
170 #else
171  NDN_THROW(CompressionError("ZSTD compression not supported!"));
172 #endif
173  }
174 
175  in.push(bio::array_source(reinterpret_cast<const char*>(buffer.data()), buffer.size()));
176  ndn::OBufferStream out;
177  bio::copy(in, out);
178 
179  return out.buf();
180 }
181 
182 std::shared_ptr<ndn::Buffer>
183 decompress(CompressionScheme scheme, ndn::span<const uint8_t> buffer)
184 {
185  namespace bio = boost::iostreams;
186 
187  bio::filtering_istreambuf in;
188 
189  switch (scheme) {
191  break;
192 
194 #ifdef PSYNC_HAVE_ZLIB
195  in.push(bio::zlib_decompressor());
196  break;
197 #else
198  NDN_THROW(CompressionError("ZLIB decompression not supported!"));
199 #endif
200 
202 #ifdef PSYNC_HAVE_GZIP
203  in.push(bio::gzip_decompressor());
204  break;
205 #else
206  NDN_THROW(CompressionError("GZIP compression not supported!"));
207 #endif
208 
210 #ifdef PSYNC_HAVE_BZIP2
211  in.push(bio::bzip2_decompressor());
212  break;
213 #else
214  NDN_THROW(CompressionError("BZIP2 compression not supported!"));
215 #endif
216 
218 #ifdef PSYNC_HAVE_LZMA
219  in.push(bio::lzma_decompressor());
220  break;
221 #else
222  NDN_THROW(CompressionError("LZMA compression not supported!"));
223 #endif
224 
226 #ifdef PSYNC_HAVE_ZSTD
227  in.push(bio::zstd_decompressor());
228  break;
229 #else
230  NDN_THROW(CompressionError("ZSTD compression not supported!"));
231 #endif
232  }
233 
234  in.push(bio::array_source(reinterpret_cast<const char*>(buffer.data()), buffer.size()));
235  ndn::OBufferStream out;
236  bio::copy(in, out);
237 
238  return out.buf();
239 }
240 
241 } // namespace psync::detail
uint32_t murmurHash3(const void *key, size_t len, uint32_t seed)
Definition: util.cpp:58
std::shared_ptr< ndn::Buffer > compress(CompressionScheme scheme, ndn::span< const uint8_t > buffer)
Definition: util.cpp:124
std::shared_ptr< ndn::Buffer > decompress(CompressionScheme scheme, ndn::span< const uint8_t > buffer)
Definition: util.cpp:183
CompressionScheme
Definition: common.hpp:43