Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
randomhash.hh
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2// Author: 2014, Tim Janik, see http://testbit.eu/
3#ifndef __ASE_RANDOMHASH_HH__
4#define __ASE_RANDOMHASH_HH__
5
6#include <ase/cxxaux.hh>
7
8namespace Ase {
9
18template<size_t SIZE>
19struct alignas (16) AlignedPOD {
21 /* malloc() aligns to 2 * sizeof (size_t), i.e. 16 on 64bit, max_align_t is
22 * usually aligned to long double, i.e. 16, and most SIMD code also needs at
23 * least 16 byte alignment.
24 */
25};
26
27// == Random Numbers ==
30int64_t random_irange (int64_t begin, int64_t end);
31double random_float ();
32double random_frange (double begin, double end);
33void random_secret (uint64_t *secret_var);
34
35// == FastRNG ==
37class Mwc256 {
38 // Based on https://prng.di.unimi.it/MWC256.c
39 uint64_t state alignas (64) [4];
40public:
41 static constexpr uint64_t MWC_A3 = 0xff377e26f82da74a;
42 Mwc256 clone192 ();
43 Mwc256 clone128 ();
44 uint64_t next ();
45 void seed ();
46 void seed (uint64_t x, uint64_t y = 0, uint64_t z = 0, uint64_t c = 1);
47 explicit Mwc256 (uint64_t x, uint64_t y = 0, uint64_t z = 0, uint64_t c = 1);
48 explicit Mwc256 ();
49 /*copy*/ Mwc256 (const Mwc256&) = default;
50 Mwc256& operator= (const Mwc256&) = default;
51};
52
53inline uint64_t
54Mwc256::next()
55{
56 const __uint128_t t = MWC_A3 * __uint128_t (state[0]) + state[3];
57 state[0] = state[1];
58 state[1] = state[2];
59 state[3] = t >> 64;
60 return state[2] = t;
61}
62
63using FastRng = Mwc256;
64
65// == Hashing ==
69struct SHA3_224 {
70 /*dtor*/ ~SHA3_224 ();
71 /*ctor*/ SHA3_224 ();
72 void reset ();
73 void update (const uint8_t *data, size_t length);
74 void digest (uint8_t hashvalue[28]);
75 void update (const String &s) { update ((const uint8_t*) &s[0], s.size()); }
76private:
77 AlignedPOD<232> mem_;
78 struct State;
79 State *state_;
80};
82void sha3_224_hash (const void *data, size_t data_length, uint8_t hashvalue[28]);
83
87struct SHA3_256 {
88 /*dtor*/ ~SHA3_256 ();
89 /*ctor*/ SHA3_256 ();
90 void reset ();
91 void update (const uint8_t *data, size_t length);
92 void digest (uint8_t hashvalue[32]);
93 void update (const String &s) { update ((const uint8_t*) &s[0], s.size()); }
94private:
95 AlignedPOD<232> mem_;
96 struct State;
97 State *state_;
98};
100void sha3_256_hash (const void *data, size_t data_length, uint8_t hashvalue[32]);
101
105struct SHA3_384 {
106 /*dtor*/ ~SHA3_384 ();
107 /*ctor*/ SHA3_384 ();
108 void reset ();
109 void update (const uint8_t *data, size_t length);
110 void digest (uint8_t hashvalue[48]);
111 void update (const String &s) { update ((const uint8_t*) &s[0], s.size()); }
112private:
113 AlignedPOD<232> mem_;
114 struct State;
115 State *state_;
116};
118void sha3_384_hash (const void *data, size_t data_length, uint8_t hashvalue[48]);
119
123struct SHA3_512 {
124 /*dtor*/ ~SHA3_512 ();
125 /*ctor*/ SHA3_512 ();
126 void reset ();
127 void update (const uint8_t *data, size_t length);
128 void digest (uint8_t hashvalue[64]);
129 void update (const String &s) { update ((const uint8_t*) &s[0], s.size()); }
130private:
131 AlignedPOD<232> mem_;
132 struct State;
133 State *state_;
134};
136void sha3_512_hash (const void *data, size_t data_length, uint8_t hashvalue[64]);
137
141struct SHAKE128 {
142 /*dtor*/ ~SHAKE128 ();
143 /*ctor*/ SHAKE128 ();
144 void reset ();
145 void update (const uint8_t *data, size_t length);
146 void squeeze_digest (uint8_t *hashvalues, size_t n);
147 void update (const String &s) { update ((const uint8_t*) &s[0], s.size()); }
148private:
149 AlignedPOD<232> mem_;
150 struct State;
151 State *state_;
152};
154void shake128_hash (const void *data, size_t data_length, uint8_t *hashvalues, size_t n);
155
159struct SHAKE256 {
160 /*dtor*/ ~SHAKE256 ();
161 /*ctor*/ SHAKE256 ();
162 void reset ();
163 void update (const uint8_t *data, size_t length);
164 void squeeze_digest (uint8_t *hashvalues, size_t n);
165 void update (const String &s) { update ((const uint8_t*) &s[0], s.size()); }
166private:
167 AlignedPOD<232> mem_;
168 struct State;
169 State *state_;
170};
172void shake256_hash (const void *data, size_t data_length, uint8_t *hashvalues, size_t n);
173
174namespace Lib { // Namespace for implementation internals
175
177class KeccakF1600 {
178 union alignas (2 * sizeof (uint64_t))
179 {
180 uint64_t A[25];
181 uint8_t bytes[200];
182 // __MMX__: __m64 V[25];
183 };
184public:
185 explicit KeccakF1600 ();
186 void reset ();
187 uint64_t& operator[] (int index) { return A[index]; }
188 uint64_t operator[] (int index) const { return A[index]; }
189 void permute (uint32_t n_rounds);
190 inline uint8_t&
191 byte (size_t state_index)
192 {
193#if __BYTE_ORDER == __LITTLE_ENDIAN
194 return bytes[(state_index / 8) * 8 + (state_index % 8)]; // 8 == sizeof (uint64_t)
195#elif __BYTE_ORDER == __BIG_ENDIAN
196 return bytes[(state_index / 8) * 8 + (8 - 1 - (state_index % 8))]; // 8 == sizeof (uint64_t)
197#else
198# error "Unknown __BYTE_ORDER"
199#endif
200 }
201};
202
203} // Lib
204
207public:
209 static uint64 random () { return random_int64(); }
211 uint64 operator() () const { return this->random(); }
213 template<typename RandomAccessIterator> void
214 generate (RandomAccessIterator begin, RandomAccessIterator end)
215 {
217 while (begin != end)
218 {
219 const uint64_t rbits = operator()();
220 *begin++ = Value (rbits);
221 if (sizeof (Value) <= 4 && begin != end)
222 *begin++ = Value (rbits >> 32);
223 }
224 }
225};
226
234 const uint16_t bit_rate_, n_rounds_;
235 uint32_t opos_;
236 Lib::KeccakF1600 state_;
237 void permute1600();
238public:
239 /*copy*/ KeccakRng (const KeccakRng&) = default;
243 inline size_t n_nums() const { return bit_rate_ / 64; }
245 inline size_t bit_capacity() const { return 1600 - bit_rate_; }
246 /*dtor*/ ~KeccakRng ();
248 explicit
249 KeccakRng (uint16_t hidden_state_capacity, uint16_t n_rounds) :
250 bit_rate_ (1600 - hidden_state_capacity), n_rounds_ (n_rounds), opos_ (n_nums())
251 {
252 ASE_ASSERT_RETURN (hidden_state_capacity > 0 && hidden_state_capacity <= 1600 - 64);
253 ASE_ASSERT_RETURN (64 * (hidden_state_capacity / 64) == hidden_state_capacity); // capacity must be 64bit aligned
254 ASE_ASSERT_RETURN (n_rounds > 0 && n_rounds < 255); // see KECCAK_ROUND_CONSTANTS access
255 }
256 void forget ();
257 void discard (unsigned long long count);
258 void xor_seed (const uint64_t *seeds, size_t n_seeds);
260 void seed (uint64_t seed_value = 1) { seed (&seed_value, 1); }
262 void
263 seed (const uint64_t *seeds, size_t n_seeds)
264 {
265 state_.reset();
266 xor_seed (seeds, n_seeds);
267 }
269 template<class SeedSeq> void
270 seed (SeedSeq &seed_sequence)
271 {
272 uint32_t u32[50]; // fill 50 * 32 = 1600 state bits
273 seed_sequence.generate (&u32[0], &u32[50]);
274 uint64_t u64[25];
275 for (size_t i = 0; i < 25; i++) // Keccak bit order: 1) LSB 2) MSB
276 u64[i] = u32[i * 2] | (uint64_t (u32[i * 2 + 1]) << 32);
277 seed (u64, 25);
278 }
280 void auto_seed ();
285 {
286 if (opos_ >= n_nums())
287 permute1600();
288 return state_[opos_++];
289 }
293 template<typename RandomAccessIterator> void
294 generate (RandomAccessIterator begin, RandomAccessIterator end)
295 {
297 while (begin != end)
298 {
299 const uint64_t rbits = operator()();
300 *begin++ = Value (rbits);
301 if (sizeof (Value) <= 4 && begin != end)
302 *begin++ = Value (rbits >> 32);
303 }
304 }
306 friend bool
307 operator== (const KeccakRng &lhs, const KeccakRng &rhs)
308 {
309 for (size_t i = 0; i < 25; i++)
310 if (lhs.state_[i] != rhs.state_[i])
311 return false;
312 return lhs.opos_ == rhs.opos_ && lhs.bit_rate_ == rhs.bit_rate_;
313 }
315 friend bool
316 operator!= (const KeccakRng &lhs, const KeccakRng &rhs)
317 {
318 return !(lhs == rhs);
319 }
322 min() const
323 {
325 }
328 max() const
329 {
330 return std::numeric_limits<result_type>::max(); // 18446744073709551615
331 }
333 template<typename CharT, typename Traits>
336 {
338 const typename IOS::fmtflags saved_flags = os.flags();
339 os.flags (IOS::dec | IOS::fixed | IOS::left);
340 const CharT space = os.widen (' ');
341 const CharT saved_fill = os.fill();
342 os.fill (space);
343 os << self.opos_;
344 for (size_t i = 0; i < 25; i++)
345 os << space << self.state_[i];
346 os.flags (saved_flags);
347 os.fill (saved_fill);
348 return os;
349 }
351 template<typename CharT, typename Traits>
354 {
356 const typename IOS::fmtflags saved_flags = is.flags();
357 is.flags (IOS::dec | IOS::skipws);
358 is >> self.opos_;
359 self.opos_ = std::min (self.n_nums(), size_t (self.opos_));
360 for (size_t i = 0; i < 25; i++)
361 is >> self.state_[i];
362 is.flags (saved_flags);
363 return is;
364 }
365};
366
371public:
373 explicit KeccakCryptoRng () : KeccakRng (256, 24) { auto_seed(); }
375 template<class SeedSeq>
376 explicit KeccakCryptoRng (SeedSeq &seed_sequence) : KeccakRng (256, 24) { seed (seed_sequence); }
377};
378
385class KeccakGoodRng : public KeccakRng {
386public:
388 explicit KeccakGoodRng () : KeccakRng (192, 13) { auto_seed(); }
390 template<class SeedSeq>
391 explicit KeccakGoodRng (SeedSeq &seed_sequence) : KeccakRng (192, 13) { seed (seed_sequence); }
392};
393
400class KeccakFastRng : public KeccakRng {
401public:
403 explicit KeccakFastRng () : KeccakRng (128, 8) { auto_seed(); }
405 template<class SeedSeq>
406 explicit KeccakFastRng (SeedSeq &seed_sequence) : KeccakRng (128, 8) { seed (seed_sequence); }
407};
408
420class Pcg32Rng {
421 uint64_t increment_; // must be odd, allows for 2^63 distinct random sequences
422 uint64_t accu_; // can contain all 2^64 possible values
423 static constexpr const uint64_t A = 6364136223846793005ULL; // from C. E. Hayness, see TAOCP by D. E. Knuth, 3.3.4, table 1, line 26.
424 static inline constexpr uint32_t
425 ror32 (const uint32_t bits, const uint32_t offset)
426 {
427 // bitwise rotate-right pattern recognized by gcc & clang iff 32==sizeof (bits)
428 return (bits >> offset) | (bits << ((32 - offset) & 31));
429 }
430 static inline constexpr uint32_t
431 pcg_xsh_rr (const uint64_t input)
432 {
433 // Section 6.3.1. 32-bit Output, 64-bit State: PCG-XSH-RR
434 // http://www.pcg-random.org/pdf/toms-oneill-pcg-family-v1.02.pdf
435 return ror32 ((input ^ (input >> 18)) >> 27, input >> 59);
436 }
437public:
439 template<class SeedSeq>
440 explicit Pcg32Rng (SeedSeq &seed_sequence) : increment_ (0), accu_ (0) { seed (seed_sequence); }
442 explicit Pcg32Rng (uint64_t offset, uint64_t sequence);
444 explicit Pcg32Rng ();
446 void auto_seed ();
448 void seed (uint64_t offset, uint64_t sequence);
450 template<class SeedSeq> void
451 seed (SeedSeq &seed_sequence)
452 {
453 uint64_t seeds[2];
454 seed_sequence.generate (&seeds[0], &seeds[2]);
455 seed (seeds[0], seeds[1]);
456 }
460 {
461 const uint64_t lcgout = accu_; // using the *last* state as ouput helps with CPU pipelining
462 accu_ = A * accu_ + increment_;
463 return pcg_xsh_rr (lcgout); // PCG XOR-shift + random rotation
464 }
465};
466
467// == Hashing ==
474template<class Num> static inline constexpr uint64_t
475fnv1a_consthash64 (const Num *ztdata)
476{
477 static_assert (sizeof (Num) <= 1, "");
478 uint64_t hash = 0xcbf29ce484222325;
479 while (ASE_ISLIKELY (*ztdata != 0))
480 hash = 0x100000001b3 * (uint8_t (*ztdata++) ^ hash);
481 return hash;
482}
483
485template<class Num> static inline constexpr uint64_t
486fnv1a_consthash64 (const Num *const data, size_t length)
487{
488 static_assert (sizeof (Num) <= 1, "");
489 uint64_t hash = 0xcbf29ce484222325;
490 for (size_t j = 0; j < length; j++)
491 hash = 0x100000001b3 * (uint8_t (data[j]) ^ hash);
492 return hash;
493}
494
505template<class Num> static ASE_CONST inline uint32_t
506pcg_hash32 (const Num *data, size_t length, uint64_t seed)
507{
508 static_assert (sizeof (Num) <= 1, "");
509 uint64_t h = seed;
510 // Knuth LCG
511 h ^= 0x14057b7ef767814fULL;
512 for (size_t i = 0; ASE_ISLIKELY (i < length); i++)
513 {
514 h -= uint8_t (data[i]);
515 h *= 6364136223846793005ULL;
516 }
517 // based on pcg_detail::xsh_rr_mixin
518 const size_t rsh = h >> 59;
519 const uint32_t xsh = (h ^ (h >> 18)) >> 27;
520 const uint32_t rot = (xsh >> rsh) | (xsh << (32 - rsh));
521 return rot;
522}
523
534template<class Num> static ASE_CONST inline uint64_t
535pcg_hash64 (const Num *data, size_t length, uint64_t seed)
536{
537 static_assert (sizeof (Num) <= 1, "");
538 uint64_t h = seed;
539 // Knuth LCG
540 h ^= 0x14057b7ef767814fULL;
541 for (size_t i = 0; ASE_ISLIKELY (i < length); i++)
542 {
543 h -= uint8_t (data[i]);
544 h *= 6364136223846793005ULL;
545 }
546 // based on pcg_detail::rxs_m_xs_mixin
547 const size_t rsh = h >> 59;
548 const uint64_t rxs = h ^ (h >> (5 + rsh));
549 const uint64_t m = rxs * 12605985483714917081ULL;
550 const uint64_t xs = m ^ (m >> 43);
551 return xs;
552}
553
555static ASE_CONST inline uint64_t
556pcg_hash64 (const char *ztdata, uint64_t seed)
557{
558 uint64_t h = seed;
559 // Knuth LCG
560 h ^= 0x14057b7ef767814fULL;
561 for (size_t i = 0; ASE_ISLIKELY (ztdata[i] != 0); i++)
562 {
563 h -= uint8_t (ztdata[i]);
564 h *= 6364136223846793005ULL;
565 }
566 // based on pcg_detail::rxs_m_xs_mixin
567 const size_t rsh = h >> 59;
568 const uint64_t rxs = h ^ (h >> (5 + rsh));
569 const uint64_t m = rxs * 12605985483714917081ULL;
570 const uint64_t xs = m ^ (m >> 43);
571 return xs;
572}
573
575
577static ASE_PURE inline uint64_t
578hash_secret ()
579{
582 return cached_hash_secret;
583}
584
586template<class Num> static ASE_CONST inline uint64_t
587byte_hash64 (const Num *data, size_t length)
588{
589 static_assert (sizeof (Num) <= 1, "");
590 return pcg_hash64 (data, length, hash_secret());
591}
592
594static ASE_CONST inline uint64_t
595string_hash64 (const std::string &string)
596{
597 return pcg_hash64 (string.data(), string.size(), hash_secret());
598}
599
601static ASE_CONST inline uint64_t
602string_hash64 (const char *ztdata)
603{
604 return pcg_hash64 (ztdata, hash_secret());
605}
606
607} // Ase
608
609#endif // __ASE_RANDOMHASH_HH__
AutoSeeder provides non-deterministic seeding entropy.
uint64 operator()() const
Generate non-deterministic 64bit random value.
void generate(RandomAccessIterator begin, RandomAccessIterator end)
Fill the range [begin, end) with random unsigned integer values.
static uint64 random()
Generate non-deterministic 64bit random value.
KeccakCryptoRng(SeedSeq &seed_sequence)
Initialize and seed the generator from seed_sequence.
KeccakCryptoRng()
Initialize and seed the generator from a system specific nondeterministic random source.
KeccakFastRng()
Initialize and seed the generator from a system specific nondeterministic random source.
KeccakFastRng(SeedSeq &seed_sequence)
Initialize and seed the generator from seed_sequence.
KeccakGoodRng(SeedSeq &seed_sequence)
Initialize and seed the generator from seed_sequence.
KeccakGoodRng()
Initialize and seed the generator from a system specific nondeterministic random source.
void seed(const uint64_t *seeds, size_t n_seeds)
Reinitialize the generator state using a nuber of 64 bit seeds.
uint64_t result_type
Integral type of the KeccakRng generator results.
KeccakRng(uint16_t hidden_state_capacity, uint16_t n_rounds)
Create an unseeded Keccak PRNG with specific capacity and number of rounds, for experts only.
void generate(RandomAccessIterator begin, RandomAccessIterator end)
Fill the range [begin, end) with random unsigned integer values.
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const KeccakRng &self)
Serialize generator state into an OStream.
result_type operator()()
Generate uniformly distributed 32 bit pseudo random number.
size_t bit_capacity() const
Amount of bits used to store hidden random number generator state.
uint64_t random()
void auto_seed()
Seed the generator from a system specific nondeterministic random source.
void discard(unsigned long long count)
void seed(uint64_t seed_value=1)
Reinitialize the generator state using a 64 bit seed_value.
friend bool operator!=(const KeccakRng &lhs, const KeccakRng &rhs)
Compare two generators for state inequality.
size_t n_nums() const
Amount of 64 bit random numbers per generated block.
result_type min() const
Minimum of the result type, for uint64_t that is 0.
void seed(SeedSeq &seed_sequence)
Seed the generator state from a seed_sequence.
void xor_seed(const uint64_t *seeds, size_t n_seeds)
friend bool operator==(const KeccakRng &lhs, const KeccakRng &rhs)
Compare two generators for state equality.
~KeccakRng()
The destructor resets the generator state to avoid leaving memory trails.
result_type max() const
Maximum of the result type, for uint64_t that is 18446744073709551615.
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, KeccakRng &self)
Deserialize generator state from an IStream.
Marsaglia multiply-with-carry generator, period ca 2^255.
Definition randomhash.hh:37
Pcg32Rng(SeedSeq &seed_sequence)
Initialize and seed from seed_sequence.
void auto_seed()
Seed the generator from a system specific nondeterministic random source.
uint32_t random()
Generate uniformly distributed 32 bit pseudo random number.
Pcg32Rng()
Initialize and seed the generator from a system specific nondeterministic random source.
void seed(SeedSeq &seed_sequence)
Seed the generator state from a seed_sequence.
void seed(uint64_t offset, uint64_t sequence)
Seed by seeking to position offset within stream sequence.
#define ASE_ASSERT_RETURN(expr,...)
Return from the current function if expr evaluates to false and issue an assertion warning.
Definition cxxaux.hh:82
#define ASE_UNLIKELY(expr)
Compiler hint to optimize for expr evaluating to false.
Definition cxxaux.hh:46
#define ASE_ISLIKELY(expr)
Compiler hint to optimize for expr evaluating to true.
Definition cxxaux.hh:45
T data(T... args)
T max(T... args)
T min(T... args)
The Anklang C++ API namespace.
Definition api.hh:9
void sha3_224_hash(const void *data, size_t data_length, uint8_t hashvalue[28])
Calculate 224 bit SHA3 digest from data, see also class SHA3_224.
uint64_t uint64
A 64-bit unsigned integer, use PRI*64 in format strings.
Definition cxxaux.hh:25
void shake256_hash(const void *data, size_t data_length, uint8_t *hashvalues, size_t n)
Calculate SHA3 extendable output digest for 256 bit security strength, see also class SHAKE256.
void sha3_384_hash(const void *data, size_t data_length, uint8_t hashvalue[48])
Calculate 384 bit SHA3 digest from data, see also class SHA3_384.
uint64_t cached_hash_secret
Use hash_secret() for access.
void sha3_256_hash(const void *data, size_t data_length, uint8_t hashvalue[32])
Calculate 256 bit SHA3 digest from data, see also class SHA3_256.
int64_t random_irange(int64_t begin, int64_t end)
void sha3_512_hash(const void *data, size_t data_length, uint8_t hashvalue[64])
Calculate 512 bit SHA3 digest from data, see also class SHA3_512.
uint64_t random_nonce()
Provide a unique 64 bit identifier that is not 0, see also random_int64().
void shake128_hash(const void *data, size_t data_length, uint8_t *hashvalues, size_t n)
Calculate SHA3 extendable output digest for 128 bit security strength, see also class SHAKE128.
double random_float()
double random_frange(double begin, double end)
uint64_t random_int64()
void random_secret(uint64_t *secret_var)
Generate a secret non-zero nonce in secret_var, unless it has already been assigned.
T size(T... args)
typedef uint64_t
SHA3_224()
Create context to calculate a 224 bit SHA3 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void digest(uint8_t hashvalue[28])
Retrieve the resulting hash value.
void reset()
Reset state to feed and retrieve a new hash value.
SHA3_256()
Create context to calculate a 256 bit SHA3 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void digest(uint8_t hashvalue[32])
Retrieve the resulting hash value.
void reset()
Reset state to feed and retrieve a new hash value.
void reset()
Reset state to feed and retrieve a new hash value.
SHA3_384()
Create context to calculate a 384 bit SHA3 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void digest(uint8_t hashvalue[48])
Retrieve the resulting hash value.
void digest(uint8_t hashvalue[64])
Retrieve the resulting hash value.
SHA3_512()
Create context to calculate a 512 bit SHA3 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void reset()
Reset state to feed and retrieve a new hash value.
SHAKE128()
Create context to calculate an unbounded SHAKE128 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void reset()
Reset state to feed and retrieve a new hash value.
void squeeze_digest(uint8_t *hashvalues, size_t n)
Retrieve an arbitrary number of hash value bytes.
void reset()
Reset state to feed and retrieve a new hash value.
SHAKE256()
Create context to calculate an unbounded SHAKE256 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void squeeze_digest(uint8_t *hashvalues, size_t n)
Retrieve an arbitrary number of hash value bytes.
Value type used to interface with various property types.
Definition value.hh:54
typedef size_t