sparsam 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|