sparsam 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +19 -0
- data/ext/extconf.rb +18 -0
- data/ext/ruby_hooks.c +96 -0
- data/ext/serializer.cpp +716 -0
- data/ext/serializer.h +101 -0
- data/ext/third-party/sparsepp/sparsepp/spp.h +4347 -0
- data/ext/third-party/sparsepp/sparsepp/spp_config.h +781 -0
- data/ext/third-party/sparsepp/sparsepp/spp_dlalloc.h +4023 -0
- data/ext/third-party/sparsepp/sparsepp/spp_memory.h +121 -0
- data/ext/third-party/sparsepp/sparsepp/spp_smartptr.h +76 -0
- data/ext/third-party/sparsepp/sparsepp/spp_stdint.h +16 -0
- data/ext/third-party/sparsepp/sparsepp/spp_timer.h +58 -0
- data/ext/third-party/sparsepp/sparsepp/spp_traits.h +122 -0
- data/ext/third-party/sparsepp/sparsepp/spp_utils.h +447 -0
- data/lib/sparsam.rb +10 -0
- data/lib/sparsam/base_class.rb +97 -0
- data/lib/sparsam/deserializer.rb +8 -0
- data/lib/sparsam/exceptions.rb +33 -0
- data/lib/sparsam/struct.rb +45 -0
- data/lib/sparsam/types.rb +108 -0
- data/lib/sparsam/union.rb +72 -0
- data/spec/gen-ruby/user_constants.rb +9 -0
- data/spec/gen-ruby/user_types.rb +106 -0
- data/spec/sparsam_spec.rb +304 -0
- data/spec/user.thrift +62 -0
- metadata +172 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
#if !defined(spp_memory_h_guard)
|
2
|
+
#define spp_memory_h_guard
|
3
|
+
|
4
|
+
#include <cstdint>
|
5
|
+
#include <cstring>
|
6
|
+
#include <cstdlib>
|
7
|
+
|
8
|
+
#if defined(_WIN32) || defined( __CYGWIN__)
|
9
|
+
#define SPP_WIN
|
10
|
+
#endif
|
11
|
+
|
12
|
+
#ifdef SPP_WIN
|
13
|
+
#include <windows.h>
|
14
|
+
#include <Psapi.h>
|
15
|
+
#undef min
|
16
|
+
#undef max
|
17
|
+
#else
|
18
|
+
#include <sys/types.h>
|
19
|
+
#include <sys/sysinfo.h>
|
20
|
+
#endif
|
21
|
+
|
22
|
+
namespace spp
|
23
|
+
{
|
24
|
+
uint64_t GetSystemMemory()
|
25
|
+
{
|
26
|
+
#ifdef SPP_WIN
|
27
|
+
MEMORYSTATUSEX memInfo;
|
28
|
+
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
|
29
|
+
GlobalMemoryStatusEx(&memInfo);
|
30
|
+
return static_cast<uint64_t>(memInfo.ullTotalPageFile);
|
31
|
+
#else
|
32
|
+
struct sysinfo memInfo;
|
33
|
+
sysinfo (&memInfo);
|
34
|
+
auto totalVirtualMem = memInfo.totalram;
|
35
|
+
|
36
|
+
totalVirtualMem += memInfo.totalswap;
|
37
|
+
totalVirtualMem *= memInfo.mem_unit;
|
38
|
+
return static_cast<uint64_t>(totalVirtualMem);
|
39
|
+
#endif
|
40
|
+
}
|
41
|
+
|
42
|
+
uint64_t GetTotalMemoryUsed()
|
43
|
+
{
|
44
|
+
#ifdef SPP_WIN
|
45
|
+
MEMORYSTATUSEX memInfo;
|
46
|
+
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
|
47
|
+
GlobalMemoryStatusEx(&memInfo);
|
48
|
+
return static_cast<uint64_t>(memInfo.ullTotalPageFile - memInfo.ullAvailPageFile);
|
49
|
+
#else
|
50
|
+
struct sysinfo memInfo;
|
51
|
+
sysinfo(&memInfo);
|
52
|
+
auto virtualMemUsed = memInfo.totalram - memInfo.freeram;
|
53
|
+
|
54
|
+
virtualMemUsed += memInfo.totalswap - memInfo.freeswap;
|
55
|
+
virtualMemUsed *= memInfo.mem_unit;
|
56
|
+
|
57
|
+
return static_cast<uint64_t>(virtualMemUsed);
|
58
|
+
#endif
|
59
|
+
}
|
60
|
+
|
61
|
+
uint64_t GetProcessMemoryUsed()
|
62
|
+
{
|
63
|
+
#ifdef SPP_WIN
|
64
|
+
PROCESS_MEMORY_COUNTERS_EX pmc;
|
65
|
+
GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast<PPROCESS_MEMORY_COUNTERS>(&pmc), sizeof(pmc));
|
66
|
+
return static_cast<uint64_t>(pmc.PrivateUsage);
|
67
|
+
#else
|
68
|
+
auto parseLine =
|
69
|
+
[](char* line)->int
|
70
|
+
{
|
71
|
+
auto i = strlen(line);
|
72
|
+
|
73
|
+
while(*line < '0' || *line > '9')
|
74
|
+
{
|
75
|
+
line++;
|
76
|
+
}
|
77
|
+
|
78
|
+
line[i-3] = '\0';
|
79
|
+
i = atoi(line);
|
80
|
+
return i;
|
81
|
+
};
|
82
|
+
|
83
|
+
auto file = fopen("/proc/self/status", "r");
|
84
|
+
auto result = -1;
|
85
|
+
char line[128];
|
86
|
+
|
87
|
+
while(fgets(line, 128, file) != nullptr)
|
88
|
+
{
|
89
|
+
if(strncmp(line, "VmSize:", 7) == 0)
|
90
|
+
{
|
91
|
+
result = parseLine(line);
|
92
|
+
break;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
fclose(file);
|
97
|
+
return static_cast<uint64_t>(result) * 1024;
|
98
|
+
#endif
|
99
|
+
}
|
100
|
+
|
101
|
+
uint64_t GetPhysicalMemory()
|
102
|
+
{
|
103
|
+
#ifdef SPP_WIN
|
104
|
+
MEMORYSTATUSEX memInfo;
|
105
|
+
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
|
106
|
+
GlobalMemoryStatusEx(&memInfo);
|
107
|
+
return static_cast<uint64_t>(memInfo.ullTotalPhys);
|
108
|
+
#else
|
109
|
+
struct sysinfo memInfo;
|
110
|
+
sysinfo(&memInfo);
|
111
|
+
|
112
|
+
auto totalPhysMem = memInfo.totalram;
|
113
|
+
|
114
|
+
totalPhysMem *= memInfo.mem_unit;
|
115
|
+
return static_cast<uint64_t>(totalPhysMem);
|
116
|
+
#endif
|
117
|
+
}
|
118
|
+
|
119
|
+
}
|
120
|
+
|
121
|
+
#endif // spp_memory_h_guard
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#if !defined(spp_smartptr_h_guard)
|
2
|
+
#define spp_smartptr_h_guard
|
3
|
+
|
4
|
+
|
5
|
+
/* -----------------------------------------------------------------------------------------------
|
6
|
+
* quick version of intrusive_ptr
|
7
|
+
* -----------------------------------------------------------------------------------------------
|
8
|
+
*/
|
9
|
+
|
10
|
+
#include <cassert>
|
11
|
+
#include <sparsepp/spp_config.h>
|
12
|
+
|
13
|
+
// ------------------------------------------------------------------------
|
14
|
+
class spp_rc
|
15
|
+
{
|
16
|
+
public:
|
17
|
+
spp_rc() : _cnt(0) {}
|
18
|
+
spp_rc(const spp_rc &) : _cnt(0) {}
|
19
|
+
void increment() const { ++_cnt; }
|
20
|
+
void decrement() const { assert(_cnt); if (--_cnt == 0) delete this; }
|
21
|
+
unsigned count() const { return _cnt; }
|
22
|
+
|
23
|
+
protected:
|
24
|
+
virtual ~spp_rc() {}
|
25
|
+
|
26
|
+
private:
|
27
|
+
mutable unsigned _cnt;
|
28
|
+
};
|
29
|
+
|
30
|
+
// ------------------------------------------------------------------------
|
31
|
+
template <class T>
|
32
|
+
class spp_sptr
|
33
|
+
{
|
34
|
+
public:
|
35
|
+
spp_sptr() : _p(0) {}
|
36
|
+
spp_sptr(T *p) : _p(p) { if (_p) _p->increment(); }
|
37
|
+
spp_sptr(const spp_sptr &o) : _p(o._p) { if (_p) _p->increment(); }
|
38
|
+
#ifndef SPP_NO_CXX11_RVALUE_REFERENCES
|
39
|
+
spp_sptr(spp_sptr &&o) : _p(o._p) { o._p = (T *)0; }
|
40
|
+
spp_sptr& operator=(spp_sptr &&o)
|
41
|
+
{
|
42
|
+
if (_p) _p->decrement();
|
43
|
+
_p = o._p;
|
44
|
+
o._p = (T *)0;
|
45
|
+
}
|
46
|
+
#endif
|
47
|
+
~spp_sptr() { if (_p) _p->decrement(); }
|
48
|
+
spp_sptr& operator=(const spp_sptr &o) { reset(o._p); return *this; }
|
49
|
+
T* get() const { return _p; }
|
50
|
+
void swap(spp_sptr &o) { T *tmp = _p; _p = o._p; o._p = tmp; }
|
51
|
+
void reset(const T *p = 0)
|
52
|
+
{
|
53
|
+
if (p == _p)
|
54
|
+
return;
|
55
|
+
if (_p) _p->decrement();
|
56
|
+
_p = (T *)p;
|
57
|
+
if (_p) _p->increment();
|
58
|
+
}
|
59
|
+
T* operator->() const { return const_cast<T *>(_p); }
|
60
|
+
bool operator!() const { return _p == 0; }
|
61
|
+
|
62
|
+
private:
|
63
|
+
T *_p;
|
64
|
+
};
|
65
|
+
|
66
|
+
// ------------------------------------------------------------------------
|
67
|
+
namespace std
|
68
|
+
{
|
69
|
+
template <class T>
|
70
|
+
inline void swap(spp_sptr<T> &a, spp_sptr<T> &b)
|
71
|
+
{
|
72
|
+
a.swap(b);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
#endif // spp_smartptr_h_guard
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#if !defined(spp_stdint_h_guard)
|
2
|
+
#define spp_stdint_h_guard
|
3
|
+
|
4
|
+
#include <sparsepp/spp_config.h>
|
5
|
+
|
6
|
+
#if defined(SPP_HAS_CSTDINT) && (__cplusplus >= 201103)
|
7
|
+
#include <cstdint>
|
8
|
+
#else
|
9
|
+
#if defined(__FreeBSD__) || defined(__IBMCPP__) || defined(_AIX)
|
10
|
+
#include <inttypes.h>
|
11
|
+
#else
|
12
|
+
#include <stdint.h>
|
13
|
+
#endif
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#endif // spp_stdint_h_guard
|
@@ -0,0 +1,58 @@
|
|
1
|
+
/**
|
2
|
+
Copyright (c) 2016 Mariano Gonzalez
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
6
|
+
in the Software without restriction, including without limitation the rights
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
9
|
+
furnished to do so, subject to the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
12
|
+
copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
20
|
+
SOFTWARE.
|
21
|
+
*/
|
22
|
+
|
23
|
+
#ifndef spp_timer_h_guard
|
24
|
+
#define spp_timer_h_guard
|
25
|
+
|
26
|
+
#include <chrono>
|
27
|
+
|
28
|
+
namespace spp
|
29
|
+
{
|
30
|
+
template<typename time_unit = std::milli>
|
31
|
+
class Timer
|
32
|
+
{
|
33
|
+
public:
|
34
|
+
Timer() { reset(); }
|
35
|
+
void reset() { _start = _snap = clock::now(); }
|
36
|
+
void snap() { _snap = clock::now(); }
|
37
|
+
|
38
|
+
float get_total() const { return get_diff<float>(_start, clock::now()); }
|
39
|
+
float get_delta() const { return get_diff<float>(_snap, clock::now()); }
|
40
|
+
|
41
|
+
private:
|
42
|
+
using clock = std::chrono::high_resolution_clock;
|
43
|
+
using point = std::chrono::time_point<clock>;
|
44
|
+
|
45
|
+
template<typename T>
|
46
|
+
static T get_diff(const point& start, const point& end)
|
47
|
+
{
|
48
|
+
using duration_t = std::chrono::duration<T, time_unit>;
|
49
|
+
|
50
|
+
return std::chrono::duration_cast<duration_t>(end - start).count();
|
51
|
+
}
|
52
|
+
|
53
|
+
point _start;
|
54
|
+
point _snap;
|
55
|
+
};
|
56
|
+
}
|
57
|
+
|
58
|
+
#endif // spp_timer_h_guard
|
@@ -0,0 +1,122 @@
|
|
1
|
+
#if !defined(spp_traits_h_guard)
|
2
|
+
#define spp_traits_h_guard
|
3
|
+
|
4
|
+
#include <sparsepp/spp_config.h>
|
5
|
+
|
6
|
+
template<int S, int H> class HashObject; // for Google's benchmark, not in spp namespace!
|
7
|
+
|
8
|
+
namespace spp_
|
9
|
+
{
|
10
|
+
|
11
|
+
// ---------------------------------------------------------------------------
|
12
|
+
// type_traits we need
|
13
|
+
// ---------------------------------------------------------------------------
|
14
|
+
template<class T, T v>
|
15
|
+
struct integral_constant { static const T value = v; };
|
16
|
+
|
17
|
+
template <class T, T v> const T integral_constant<T, v>::value;
|
18
|
+
|
19
|
+
typedef integral_constant<bool, true> true_type;
|
20
|
+
typedef integral_constant<bool, false> false_type;
|
21
|
+
|
22
|
+
typedef integral_constant<int, 0> zero_type;
|
23
|
+
typedef integral_constant<int, 1> one_type;
|
24
|
+
typedef integral_constant<int, 2> two_type;
|
25
|
+
typedef integral_constant<int, 3> three_type;
|
26
|
+
|
27
|
+
template<typename T, typename U> struct is_same : public false_type { };
|
28
|
+
template<typename T> struct is_same<T, T> : public true_type { };
|
29
|
+
|
30
|
+
template<typename T> struct remove_const { typedef T type; };
|
31
|
+
template<typename T> struct remove_const<T const> { typedef T type; };
|
32
|
+
|
33
|
+
template<typename T> struct remove_volatile { typedef T type; };
|
34
|
+
template<typename T> struct remove_volatile<T volatile> { typedef T type; };
|
35
|
+
|
36
|
+
template<typename T> struct remove_cv
|
37
|
+
{
|
38
|
+
typedef typename remove_const<typename remove_volatile<T>::type>::type type;
|
39
|
+
};
|
40
|
+
|
41
|
+
// ---------------- is_integral ----------------------------------------
|
42
|
+
template <class T> struct is_integral;
|
43
|
+
template <class T> struct is_integral : false_type { };
|
44
|
+
template<> struct is_integral<bool> : true_type { };
|
45
|
+
template<> struct is_integral<char> : true_type { };
|
46
|
+
template<> struct is_integral<unsigned char> : true_type { };
|
47
|
+
template<> struct is_integral<signed char> : true_type { };
|
48
|
+
template<> struct is_integral<short> : true_type { };
|
49
|
+
template<> struct is_integral<unsigned short> : true_type { };
|
50
|
+
template<> struct is_integral<int> : true_type { };
|
51
|
+
template<> struct is_integral<unsigned int> : true_type { };
|
52
|
+
template<> struct is_integral<long> : true_type { };
|
53
|
+
template<> struct is_integral<unsigned long> : true_type { };
|
54
|
+
#ifdef SPP_HAS_LONG_LONG
|
55
|
+
template<> struct is_integral<long long> : true_type { };
|
56
|
+
template<> struct is_integral<unsigned long long> : true_type { };
|
57
|
+
#endif
|
58
|
+
template <class T> struct is_integral<const T> : is_integral<T> { };
|
59
|
+
template <class T> struct is_integral<volatile T> : is_integral<T> { };
|
60
|
+
template <class T> struct is_integral<const volatile T> : is_integral<T> { };
|
61
|
+
|
62
|
+
// ---------------- is_floating_point ----------------------------------------
|
63
|
+
template <class T> struct is_floating_point;
|
64
|
+
template <class T> struct is_floating_point : false_type { };
|
65
|
+
template<> struct is_floating_point<float> : true_type { };
|
66
|
+
template<> struct is_floating_point<double> : true_type { };
|
67
|
+
template<> struct is_floating_point<long double> : true_type { };
|
68
|
+
template <class T> struct is_floating_point<const T> : is_floating_point<T> { };
|
69
|
+
template <class T> struct is_floating_point<volatile T> : is_floating_point<T> { };
|
70
|
+
template <class T> struct is_floating_point<const volatile T> : is_floating_point<T> { };
|
71
|
+
|
72
|
+
// ---------------- is_pointer ----------------------------------------
|
73
|
+
template <class T> struct is_pointer;
|
74
|
+
template <class T> struct is_pointer : false_type { };
|
75
|
+
template <class T> struct is_pointer<T*> : true_type { };
|
76
|
+
template <class T> struct is_pointer<const T> : is_pointer<T> { };
|
77
|
+
template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
|
78
|
+
template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
|
79
|
+
|
80
|
+
// ---------------- is_reference ----------------------------------------
|
81
|
+
template <class T> struct is_reference;
|
82
|
+
template<typename T> struct is_reference : false_type {};
|
83
|
+
template<typename T> struct is_reference<T&> : true_type {};
|
84
|
+
|
85
|
+
// ---------------- is_relocatable ----------------------------------------
|
86
|
+
// relocatable values can be moved around in memory using memcpy and remain
|
87
|
+
// correct. Most types are relocatable, an example of a type who is not would
|
88
|
+
// be a struct which contains a pointer to a buffer inside itself - this is the
|
89
|
+
// case for std::string in gcc 5.
|
90
|
+
// ------------------------------------------------------------------------
|
91
|
+
template <class T> struct is_relocatable;
|
92
|
+
template <class T> struct is_relocatable :
|
93
|
+
integral_constant<bool, (is_integral<T>::value || is_floating_point<T>::value)>
|
94
|
+
{ };
|
95
|
+
|
96
|
+
template<int S, int H> struct is_relocatable<HashObject<S, H> > : true_type { };
|
97
|
+
|
98
|
+
template <class T> struct is_relocatable<const T> : is_relocatable<T> { };
|
99
|
+
template <class T> struct is_relocatable<volatile T> : is_relocatable<T> { };
|
100
|
+
template <class T> struct is_relocatable<const volatile T> : is_relocatable<T> { };
|
101
|
+
template <class A, int N> struct is_relocatable<A[N]> : is_relocatable<A> { };
|
102
|
+
template <class T, class U> struct is_relocatable<std::pair<T, U> > :
|
103
|
+
integral_constant<bool, (is_relocatable<T>::value && is_relocatable<U>::value)>
|
104
|
+
{ };
|
105
|
+
|
106
|
+
// A template helper used to select A or B based on a condition.
|
107
|
+
// ------------------------------------------------------------
|
108
|
+
template<bool cond, typename A, typename B>
|
109
|
+
struct if_
|
110
|
+
{
|
111
|
+
typedef A type;
|
112
|
+
};
|
113
|
+
|
114
|
+
template<typename A, typename B>
|
115
|
+
struct if_<false, A, B>
|
116
|
+
{
|
117
|
+
typedef B type;
|
118
|
+
};
|
119
|
+
|
120
|
+
} // spp_ namespace
|
121
|
+
|
122
|
+
#endif // spp_traits_h_guard
|
@@ -0,0 +1,447 @@
|
|
1
|
+
// ----------------------------------------------------------------------
|
2
|
+
// Copyright (c) 2016, Steven Gregory Popovitch - greg7mdp@gmail.com
|
3
|
+
// All rights reserved.
|
4
|
+
//
|
5
|
+
// Code derived derived from Boost libraries.
|
6
|
+
// Boost software licence reproduced below.
|
7
|
+
//
|
8
|
+
// Redistribution and use in source and binary forms, with or without
|
9
|
+
// modification, are permitted provided that the following conditions are
|
10
|
+
// met:
|
11
|
+
//
|
12
|
+
// * Redistributions of source code must retain the above copyright
|
13
|
+
// notice, this list of conditions and the following disclaimer.
|
14
|
+
// * Redistributions in binary form must reproduce the above
|
15
|
+
// copyright notice, this list of conditions and the following disclaimer
|
16
|
+
// in the documentation and/or other materials provided with the
|
17
|
+
// distribution.
|
18
|
+
// * The name of Steven Gregory Popovitch may not be used to
|
19
|
+
// endorse or promote products derived from this software without
|
20
|
+
// specific prior written permission.
|
21
|
+
//
|
22
|
+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
23
|
+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
24
|
+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
25
|
+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
26
|
+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
27
|
+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
28
|
+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
29
|
+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
30
|
+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
31
|
+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
32
|
+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
// ----------------------------------------------------------------------
|
34
|
+
|
35
|
+
// ---------------------------------------------------------------------------
|
36
|
+
// Boost Software License - Version 1.0 - August 17th, 2003
|
37
|
+
//
|
38
|
+
// Permission is hereby granted, free of charge, to any person or organization
|
39
|
+
// obtaining a copy of the software and accompanying documentation covered by
|
40
|
+
// this license (the "Software") to use, reproduce, display, distribute,
|
41
|
+
// execute, and transmit the Software, and to prepare derivative works of the
|
42
|
+
// Software, and to permit third-parties to whom the Software is furnished to
|
43
|
+
// do so, all subject to the following:
|
44
|
+
//
|
45
|
+
// The copyright notices in the Software and this entire statement, including
|
46
|
+
// the above license grant, this restriction and the following disclaimer,
|
47
|
+
// must be included in all copies of the Software, in whole or in part, and
|
48
|
+
// all derivative works of the Software, unless such copies or derivative
|
49
|
+
// works are solely in the form of machine-executable object code generated by
|
50
|
+
// a source language processor.
|
51
|
+
//
|
52
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
53
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
54
|
+
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
55
|
+
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
56
|
+
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
57
|
+
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
58
|
+
// DEALINGS IN THE SOFTWARE.
|
59
|
+
// ---------------------------------------------------------------------------
|
60
|
+
|
61
|
+
// ----------------------------------------------------------------------
|
62
|
+
// H A S H F U N C T I O N S
|
63
|
+
// ----------------------------
|
64
|
+
//
|
65
|
+
// Implements spp::spp_hash() and spp::hash_combine()
|
66
|
+
// ----------------------------------------------------------------------
|
67
|
+
|
68
|
+
#if !defined(spp_utils_h_guard_)
|
69
|
+
#define spp_utils_h_guard_
|
70
|
+
|
71
|
+
#if defined(_MSC_VER)
|
72
|
+
#if (_MSC_VER >= 1600 ) // vs2010 (1900 is vs2015)
|
73
|
+
#include <functional>
|
74
|
+
#define SPP_HASH_CLASS std::hash
|
75
|
+
#else
|
76
|
+
#include <hash_map>
|
77
|
+
#define SPP_HASH_CLASS stdext::hash_compare
|
78
|
+
#endif
|
79
|
+
#if (_MSC_FULL_VER < 190021730)
|
80
|
+
#define SPP_NO_CXX11_NOEXCEPT
|
81
|
+
#endif
|
82
|
+
#elif defined __clang__
|
83
|
+
#if __has_feature(cxx_noexcept) // what to use here?
|
84
|
+
#include <functional>
|
85
|
+
#define SPP_HASH_CLASS std::hash
|
86
|
+
#else
|
87
|
+
#include <tr1/unordered_map>
|
88
|
+
#define SPP_HASH_CLASS std::tr1::hash
|
89
|
+
#endif
|
90
|
+
|
91
|
+
#if !__has_feature(cxx_noexcept)
|
92
|
+
#define SPP_NO_CXX11_NOEXCEPT
|
93
|
+
#endif
|
94
|
+
#elif defined(__GNUC__)
|
95
|
+
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
|
96
|
+
#include <functional>
|
97
|
+
#define SPP_HASH_CLASS std::hash
|
98
|
+
|
99
|
+
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) < 40600
|
100
|
+
#define SPP_NO_CXX11_NOEXCEPT
|
101
|
+
#endif
|
102
|
+
#else
|
103
|
+
#include <tr1/unordered_map>
|
104
|
+
#define SPP_HASH_CLASS std::tr1::hash
|
105
|
+
#define SPP_NO_CXX11_NOEXCEPT
|
106
|
+
#endif
|
107
|
+
#else
|
108
|
+
#include <functional>
|
109
|
+
#define SPP_HASH_CLASS std::hash
|
110
|
+
#endif
|
111
|
+
|
112
|
+
#ifdef SPP_NO_CXX11_NOEXCEPT
|
113
|
+
#define SPP_NOEXCEPT
|
114
|
+
#else
|
115
|
+
#define SPP_NOEXCEPT noexcept
|
116
|
+
#endif
|
117
|
+
|
118
|
+
#ifdef SPP_NO_CXX11_CONSTEXPR
|
119
|
+
#define SPP_CONSTEXPR
|
120
|
+
#else
|
121
|
+
#define SPP_CONSTEXPR constexpr
|
122
|
+
#endif
|
123
|
+
|
124
|
+
#define SPP_INLINE
|
125
|
+
|
126
|
+
#ifndef spp_
|
127
|
+
#define spp_ spp
|
128
|
+
#endif
|
129
|
+
|
130
|
+
namespace spp_
|
131
|
+
{
|
132
|
+
|
133
|
+
template <class T> T spp_min(T a, T b) { return a < b ? a : b; }
|
134
|
+
template <class T> T spp_max(T a, T b) { return a >= b ? a : b; }
|
135
|
+
|
136
|
+
template <class T>
|
137
|
+
struct spp_hash
|
138
|
+
{
|
139
|
+
SPP_INLINE size_t operator()(const T &__v) const SPP_NOEXCEPT
|
140
|
+
{
|
141
|
+
SPP_HASH_CLASS<T> hasher;
|
142
|
+
return hasher(__v);
|
143
|
+
}
|
144
|
+
};
|
145
|
+
|
146
|
+
template <class T>
|
147
|
+
struct spp_hash<T *>
|
148
|
+
{
|
149
|
+
static size_t spp_log2 (size_t val) SPP_NOEXCEPT
|
150
|
+
{
|
151
|
+
size_t res = 0;
|
152
|
+
while (val > 1)
|
153
|
+
{
|
154
|
+
val >>= 1;
|
155
|
+
res++;
|
156
|
+
}
|
157
|
+
return res;
|
158
|
+
}
|
159
|
+
|
160
|
+
SPP_INLINE size_t operator()(const T *__v) const SPP_NOEXCEPT
|
161
|
+
{
|
162
|
+
static const size_t shift = 3; // spp_log2(1 + sizeof(T)); // T might be incomplete!
|
163
|
+
const uintptr_t i = (const uintptr_t)__v;
|
164
|
+
return static_cast<size_t>(i >> shift);
|
165
|
+
}
|
166
|
+
};
|
167
|
+
|
168
|
+
// from http://burtleburtle.net/bob/hash/integer.html
|
169
|
+
// fast and efficient for power of two table sizes where we always
|
170
|
+
// consider the last bits.
|
171
|
+
// ---------------------------------------------------------------
|
172
|
+
inline size_t spp_mix_32(uint32_t a)
|
173
|
+
{
|
174
|
+
a = a ^ (a >> 4);
|
175
|
+
a = (a ^ 0xdeadbeef) + (a << 5);
|
176
|
+
a = a ^ (a >> 11);
|
177
|
+
return static_cast<size_t>(a);
|
178
|
+
}
|
179
|
+
|
180
|
+
// Maybe we should do a more thorough scrambling as described in
|
181
|
+
// https://gist.github.com/badboy/6267743
|
182
|
+
// -------------------------------------------------------------
|
183
|
+
inline size_t spp_mix_64(uint64_t a)
|
184
|
+
{
|
185
|
+
a = a ^ (a >> 4);
|
186
|
+
a = (a ^ 0xdeadbeef) + (a << 5);
|
187
|
+
a = a ^ (a >> 11);
|
188
|
+
return (size_t)a;
|
189
|
+
}
|
190
|
+
|
191
|
+
template <>
|
192
|
+
struct spp_hash<bool> : public std::unary_function<bool, size_t>
|
193
|
+
{
|
194
|
+
SPP_INLINE size_t operator()(bool __v) const SPP_NOEXCEPT
|
195
|
+
{ return static_cast<size_t>(__v); }
|
196
|
+
};
|
197
|
+
|
198
|
+
template <>
|
199
|
+
struct spp_hash<char> : public std::unary_function<char, size_t>
|
200
|
+
{
|
201
|
+
SPP_INLINE size_t operator()(char __v) const SPP_NOEXCEPT
|
202
|
+
{ return static_cast<size_t>(__v); }
|
203
|
+
};
|
204
|
+
|
205
|
+
template <>
|
206
|
+
struct spp_hash<signed char> : public std::unary_function<signed char, size_t>
|
207
|
+
{
|
208
|
+
SPP_INLINE size_t operator()(signed char __v) const SPP_NOEXCEPT
|
209
|
+
{ return static_cast<size_t>(__v); }
|
210
|
+
};
|
211
|
+
|
212
|
+
template <>
|
213
|
+
struct spp_hash<unsigned char> : public std::unary_function<unsigned char, size_t>
|
214
|
+
{
|
215
|
+
SPP_INLINE size_t operator()(unsigned char __v) const SPP_NOEXCEPT
|
216
|
+
{ return static_cast<size_t>(__v); }
|
217
|
+
};
|
218
|
+
|
219
|
+
template <>
|
220
|
+
struct spp_hash<wchar_t> : public std::unary_function<wchar_t, size_t>
|
221
|
+
{
|
222
|
+
SPP_INLINE size_t operator()(wchar_t __v) const SPP_NOEXCEPT
|
223
|
+
{ return static_cast<size_t>(__v); }
|
224
|
+
};
|
225
|
+
|
226
|
+
template <>
|
227
|
+
struct spp_hash<int16_t> : public std::unary_function<int16_t, size_t>
|
228
|
+
{
|
229
|
+
SPP_INLINE size_t operator()(int16_t __v) const SPP_NOEXCEPT
|
230
|
+
{ return spp_mix_32(static_cast<uint32_t>(__v)); }
|
231
|
+
};
|
232
|
+
|
233
|
+
template <>
|
234
|
+
struct spp_hash<uint16_t> : public std::unary_function<uint16_t, size_t>
|
235
|
+
{
|
236
|
+
SPP_INLINE size_t operator()(uint16_t __v) const SPP_NOEXCEPT
|
237
|
+
{ return spp_mix_32(static_cast<uint32_t>(__v)); }
|
238
|
+
};
|
239
|
+
|
240
|
+
template <>
|
241
|
+
struct spp_hash<int32_t> : public std::unary_function<int32_t, size_t>
|
242
|
+
{
|
243
|
+
SPP_INLINE size_t operator()(int32_t __v) const SPP_NOEXCEPT
|
244
|
+
{ return spp_mix_32(static_cast<uint32_t>(__v)); }
|
245
|
+
};
|
246
|
+
|
247
|
+
template <>
|
248
|
+
struct spp_hash<uint32_t> : public std::unary_function<uint32_t, size_t>
|
249
|
+
{
|
250
|
+
SPP_INLINE size_t operator()(uint32_t __v) const SPP_NOEXCEPT
|
251
|
+
{ return spp_mix_32(static_cast<uint32_t>(__v)); }
|
252
|
+
};
|
253
|
+
|
254
|
+
template <>
|
255
|
+
struct spp_hash<int64_t> : public std::unary_function<int64_t, size_t>
|
256
|
+
{
|
257
|
+
SPP_INLINE size_t operator()(int64_t __v) const SPP_NOEXCEPT
|
258
|
+
{ return spp_mix_64(static_cast<uint64_t>(__v)); }
|
259
|
+
};
|
260
|
+
|
261
|
+
template <>
|
262
|
+
struct spp_hash<uint64_t> : public std::unary_function<uint64_t, size_t>
|
263
|
+
{
|
264
|
+
SPP_INLINE size_t operator()(uint64_t __v) const SPP_NOEXCEPT
|
265
|
+
{ return spp_mix_64(static_cast<uint64_t>(__v)); }
|
266
|
+
};
|
267
|
+
|
268
|
+
template <>
|
269
|
+
struct spp_hash<float> : public std::unary_function<float, size_t>
|
270
|
+
{
|
271
|
+
SPP_INLINE size_t operator()(float __v) const SPP_NOEXCEPT
|
272
|
+
{
|
273
|
+
// -0.0 and 0.0 should return same hash
|
274
|
+
uint32_t *as_int = reinterpret_cast<uint32_t *>(&__v);
|
275
|
+
return (__v == 0) ? static_cast<size_t>(0) : spp_mix_32(*as_int);
|
276
|
+
}
|
277
|
+
};
|
278
|
+
|
279
|
+
template <>
|
280
|
+
struct spp_hash<double> : public std::unary_function<double, size_t>
|
281
|
+
{
|
282
|
+
SPP_INLINE size_t operator()(double __v) const SPP_NOEXCEPT
|
283
|
+
{
|
284
|
+
// -0.0 and 0.0 should return same hash
|
285
|
+
uint64_t *as_int = reinterpret_cast<uint64_t *>(&__v);
|
286
|
+
return (__v == 0) ? static_cast<size_t>(0) : spp_mix_64(*as_int);
|
287
|
+
}
|
288
|
+
};
|
289
|
+
|
290
|
+
template <class T, int sz> struct Combiner
|
291
|
+
{
|
292
|
+
inline void operator()(T& seed, T value);
|
293
|
+
};
|
294
|
+
|
295
|
+
template <class T> struct Combiner<T, 4>
|
296
|
+
{
|
297
|
+
inline void operator()(T& seed, T value)
|
298
|
+
{
|
299
|
+
seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
300
|
+
}
|
301
|
+
};
|
302
|
+
|
303
|
+
template <class T> struct Combiner<T, 8>
|
304
|
+
{
|
305
|
+
inline void operator()(T& seed, T value)
|
306
|
+
{
|
307
|
+
seed ^= value + T(0xc6a4a7935bd1e995) + (seed << 6) + (seed >> 2);
|
308
|
+
}
|
309
|
+
};
|
310
|
+
|
311
|
+
template <class T>
|
312
|
+
inline void hash_combine(std::size_t& seed, T const& v)
|
313
|
+
{
|
314
|
+
spp_::spp_hash<T> hasher;
|
315
|
+
Combiner<std::size_t, sizeof(std::size_t)> combiner;
|
316
|
+
|
317
|
+
combiner(seed, hasher(v));
|
318
|
+
}
|
319
|
+
|
320
|
+
static inline uint32_t s_spp_popcount_default(uint32_t i) SPP_NOEXCEPT
|
321
|
+
{
|
322
|
+
i = i - ((i >> 1) & 0x55555555);
|
323
|
+
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
|
324
|
+
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
|
325
|
+
}
|
326
|
+
|
327
|
+
static inline uint32_t s_spp_popcount_default(uint64_t x) SPP_NOEXCEPT
|
328
|
+
{
|
329
|
+
const uint64_t m1 = uint64_t(0x5555555555555555); // binary: 0101...
|
330
|
+
const uint64_t m2 = uint64_t(0x3333333333333333); // binary: 00110011..
|
331
|
+
const uint64_t m4 = uint64_t(0x0f0f0f0f0f0f0f0f); // binary: 4 zeros, 4 ones ...
|
332
|
+
const uint64_t h01 = uint64_t(0x0101010101010101); // the sum of 256 to the power of 0,1,2,3...
|
333
|
+
|
334
|
+
x -= (x >> 1) & m1; // put count of each 2 bits into those 2 bits
|
335
|
+
x = (x & m2) + ((x >> 2) & m2); // put count of each 4 bits into those 4 bits
|
336
|
+
x = (x + (x >> 4)) & m4; // put count of each 8 bits into those 8 bits
|
337
|
+
return (x * h01)>>56; // returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24)+...
|
338
|
+
}
|
339
|
+
|
340
|
+
#ifdef __APPLE__
|
341
|
+
static inline uint32_t count_trailing_zeroes(size_t v) SPP_NOEXCEPT
|
342
|
+
{
|
343
|
+
size_t x = (v & -v) - 1;
|
344
|
+
// sadly sizeof() required to build on macos
|
345
|
+
return sizeof(size_t) == 8 ? s_spp_popcount_default((uint64_t)x) : s_spp_popcount_default((uint32_t)x);
|
346
|
+
}
|
347
|
+
|
348
|
+
static inline uint32_t s_popcount(size_t v) SPP_NOEXCEPT
|
349
|
+
{
|
350
|
+
// sadly sizeof() required to build on macos
|
351
|
+
return sizeof(size_t) == 8 ? s_spp_popcount_default((uint64_t)v) : s_spp_popcount_default((uint32_t)v);
|
352
|
+
}
|
353
|
+
#else
|
354
|
+
static inline uint32_t count_trailing_zeroes(size_t v) SPP_NOEXCEPT
|
355
|
+
{
|
356
|
+
return s_spp_popcount_default((v & -(intptr_t)v) - 1);
|
357
|
+
}
|
358
|
+
|
359
|
+
static inline uint32_t s_popcount(size_t v) SPP_NOEXCEPT
|
360
|
+
{
|
361
|
+
return s_spp_popcount_default(v);
|
362
|
+
}
|
363
|
+
#endif
|
364
|
+
|
365
|
+
// -----------------------------------------------------------
|
366
|
+
// -----------------------------------------------------------
|
367
|
+
template<class T>
|
368
|
+
class libc_allocator
|
369
|
+
{
|
370
|
+
public:
|
371
|
+
typedef T value_type;
|
372
|
+
typedef T* pointer;
|
373
|
+
typedef ptrdiff_t difference_type;
|
374
|
+
typedef const T* const_pointer;
|
375
|
+
typedef size_t size_type;
|
376
|
+
|
377
|
+
libc_allocator() {}
|
378
|
+
libc_allocator(const libc_allocator &) {}
|
379
|
+
libc_allocator& operator=(const libc_allocator &) { return *this; }
|
380
|
+
|
381
|
+
#ifndef SPP_NO_CXX11_RVALUE_REFERENCES
|
382
|
+
libc_allocator(libc_allocator &&) {}
|
383
|
+
libc_allocator& operator=(libc_allocator &&) { return *this; }
|
384
|
+
#endif
|
385
|
+
|
386
|
+
pointer allocate(size_t n, const_pointer /* unused */= 0)
|
387
|
+
{
|
388
|
+
return static_cast<pointer>(malloc(n * sizeof(T)));
|
389
|
+
}
|
390
|
+
|
391
|
+
void deallocate(pointer p, size_t /* unused */)
|
392
|
+
{
|
393
|
+
free(p);
|
394
|
+
}
|
395
|
+
|
396
|
+
pointer reallocate(pointer p, size_t new_size)
|
397
|
+
{
|
398
|
+
return static_cast<pointer>(realloc(p, new_size * sizeof(T)));
|
399
|
+
}
|
400
|
+
|
401
|
+
// extra API to match spp_allocator interface
|
402
|
+
pointer reallocate(pointer p, size_t /* old_size */, size_t new_size)
|
403
|
+
{
|
404
|
+
return static_cast<pointer>(realloc(p, new_size * sizeof(T)));
|
405
|
+
}
|
406
|
+
|
407
|
+
size_type max_size() const
|
408
|
+
{
|
409
|
+
return static_cast<size_type>(-1) / sizeof(value_type);
|
410
|
+
}
|
411
|
+
|
412
|
+
void construct(pointer p, const value_type& val)
|
413
|
+
{
|
414
|
+
new(p) value_type(val);
|
415
|
+
}
|
416
|
+
|
417
|
+
void destroy(pointer p) { p->~value_type(); }
|
418
|
+
|
419
|
+
template<class U>
|
420
|
+
struct rebind
|
421
|
+
{
|
422
|
+
typedef spp_::libc_allocator<U> other;
|
423
|
+
};
|
424
|
+
|
425
|
+
};
|
426
|
+
|
427
|
+
// forward declaration
|
428
|
+
// -------------------
|
429
|
+
template<class T>
|
430
|
+
class spp_allocator;
|
431
|
+
|
432
|
+
}
|
433
|
+
|
434
|
+
template<class T>
|
435
|
+
inline bool operator==(const spp_::libc_allocator<T> &, const spp_::libc_allocator<T> &)
|
436
|
+
{
|
437
|
+
return true;
|
438
|
+
}
|
439
|
+
|
440
|
+
template<class T>
|
441
|
+
inline bool operator!=(const spp_::libc_allocator<T> &, const spp_::libc_allocator<T> &)
|
442
|
+
{
|
443
|
+
return false;
|
444
|
+
}
|
445
|
+
|
446
|
+
#endif // spp_utils_h_guard_
|
447
|
+
|