-
Notifications
You must be signed in to change notification settings - Fork 0
/
multi.hpp
124 lines (105 loc) · 3.23 KB
/
multi.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* Simple any-key/value multimap. Key order matters. zlib/libpng licensed.
* This is a std compatible-ish container in spirit of std::multimap, whereas it handles
* multiple-keys/single-value as opposed to single-key/multiple-values.
* @todo: make retrieve() much faster
* Usage:
* moon9::multinmap<char> mnm;
* // direct access
* mnm[true][-123][100.00]['a'][3.1459f]["helloworld"].get() = 'X';
* assert( mnm[true][-123][100.00]['a'][3.1459f]["helloworld"].get() == 'X' );
* // standard find
* assert( mnm[true][-123][100.00]['a'][3.1459f]["helloworld"].find() != mnm.end() );
* // custom find
* assert( mnm[true][-123][100.00]['a'][3.1459f]["helloworld"].findit() == true );
* assert( mnm[true][-123][100.00]['a'][3.1459f]["helloworld"].found() == 'X' );
* - rlyeh
*/
#pragma once
#include <map>
#include <vector>
#include <functional>
#include <string>
#include <sstream>
namespace moon9
{
template<typename VALUE>
class multinmap : public std::map< size_t, VALUE >
{
mutable struct hashes_t : public std::vector< size_t >
{
hashes_t()
{}
size_t retrieve()
{
// merge hashes into a final hash
# if 0
std::stringstream ss;
for( auto &it : *this )
ss << it;
this->clear();
return std::hash<std::string>()(ss.str());
# else
size_t hash = 0, pos = 0;
for( auto &it : *this )
hash ^= (it << (pos++ % 7));
this->clear();
return hash;
# endif
}
} hashes;
mutable typename std::map< size_t, VALUE >::iterator cursor;
public:
multinmap()
{
cursor = this->end();
}
// access
template<typename T>
multinmap &operator []( const T &t )
{
hashes.push_back( std::hash<T>()(t) );
return *this;
}
multinmap &operator []( const char *t )
{
hashes.push_back( std::hash<std::string>()(t) );
return *this;
}
const VALUE &get() const
{
size_t hash = hashes.retrieve();
std::map< size_t, VALUE > &map = *this;
return ( map[ hash ] = map[ hash ] );
}
VALUE &get()
{
size_t hash = hashes.retrieve();
std::map< size_t, VALUE > &map = *this;
return ( map[ hash ] = map[ hash ] );
}
// standard search (c++ way)
typename std::map< size_t, VALUE >::iterator find()
{
size_t hash = hashes.retrieve();
std::map< size_t, VALUE > &map = *this;
return map.find( hash );
}
// custom search (my way)
bool findit()
{
size_t hash = hashes.retrieve();
std::map< size_t, VALUE > &map = *this;
return ( ( cursor = map.find( hash ) ) != map.end() );
}
const VALUE &found() const
{
hashes.clear();
return cursor->second;
}
VALUE &found()
{
hashes.clear();
return cursor->second;
}
};
}