-rw-r--r-- | lib/pointer_map.cc | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/lib/pointer_map.cc b/lib/pointer_map.cc new file mode 100644 index 0000000..44f7ebc --- a/dev/null +++ b/lib/pointer_map.cc | |||
@@ -0,0 +1,74 @@ | |||
1 | #include <cassert> | ||
2 | #include <map> | ||
3 | #include <string> | ||
4 | using namespace std; | ||
5 | #include "konforka/exception.h" | ||
6 | #include "konforka/pointer_map.h" | ||
7 | |||
8 | namespace konforka { | ||
9 | |||
10 | /* | ||
11 | * to_t->from_t->from->to | ||
12 | */ | ||
13 | class mpointer_t { | ||
14 | public: | ||
15 | void *ptr; | ||
16 | int ref; | ||
17 | |||
18 | mpointer_t() : ptr(0), ref(0) { } | ||
19 | |||
20 | void _ref() { ref++; } | ||
21 | void _unref() { ref--; } | ||
22 | }; | ||
23 | typedef map<void*,mpointer_t> map_ptr_1_t; | ||
24 | typedef map<string,map_ptr_1_t> map_ptr_2_t; | ||
25 | typedef map<string,map_ptr_2_t> map_ptr_t; | ||
26 | |||
27 | static map_ptr_t pointer_map; | ||
28 | |||
29 | void _map_pointer(const type_info& tf,void *pf,const type_info& tt,void *pt) { | ||
30 | mpointer_t& mpt = pointer_map[tf.name()][tt.name()][pf]; | ||
31 | if(mpt.ref) { | ||
32 | if(mpt.ptr != pt) | ||
33 | throw exception(CODEPOINT,"trying to remap existing pointer with different value"); | ||
34 | }else{ | ||
35 | mpt.ptr = pt; | ||
36 | } | ||
37 | mpt.ref++; | ||
38 | } | ||
39 | void _unmap_pointer(const type_info& tf,void *pf,const type_info& tt,void *pt) { | ||
40 | map_ptr_t::iterator i1 = pointer_map.find(tf.name()); | ||
41 | if(i1==pointer_map.end()) | ||
42 | throw exception(CODEPOINT,"no pointer of such type has ever been mapped"); | ||
43 | map_ptr_2_t::iterator i2 = i1->second.find(tt.name()); | ||
44 | if(i2==i1->second.end()) | ||
45 | throw exception(CODEPOINT,"no pointer has ever been mapped to the object of this type"); | ||
46 | map_ptr_1_t::iterator i3 = i2->second.find(pf); | ||
47 | if(i3==i2->second.end()) | ||
48 | throw exception(CODEPOINT,"this pointer has never been mapped"); | ||
49 | assert(i3->second.ref>0); | ||
50 | if(--(i3->second.ref)) | ||
51 | return; | ||
52 | i2->second.erase(i3); | ||
53 | if(!i2->second.empty()) | ||
54 | return; | ||
55 | i1->second.erase(i2); | ||
56 | if(!i1->second.empty()) | ||
57 | return; | ||
58 | pointer_map.erase(i1); | ||
59 | } | ||
60 | void *_mapped_pointer(const type_info& tf,void *pf,const type_info& tt) { | ||
61 | map_ptr_t::iterator i1 = pointer_map.find(tf.name()); | ||
62 | if(i1==pointer_map.end()) | ||
63 | throw exception(CODEPOINT,"no pointer of such type has ever been mapped"); | ||
64 | map_ptr_2_t::iterator i2 = i1->second.find(tt.name()); | ||
65 | if(i2==i1->second.end()) | ||
66 | throw exception(CODEPOINT,"no pointer has ever been mapped to the object of this type"); | ||
67 | map_ptr_1_t::iterator i3 = i2->second.find(pf); | ||
68 | if(i3==i2->second.end()) | ||
69 | throw exception(CODEPOINT,"this pointer has never been mapped"); | ||
70 | assert(i3->second.ref>0); | ||
71 | return i3->second.ptr; | ||
72 | } | ||
73 | |||
74 | } | ||