File Coverage

src/panda/cast.h
Criterion Covered Total %
statement 14 16 87.5
branch 9 22 40.9
condition n/a
subroutine n/a
pod n/a
total 23 38 60.5


line stmt bran cond sub pod time code
1             #pragma once
2             #include
3             #include
4             #include
5             #include
6             #include
7              
8             namespace panda {
9              
10             namespace detail { namespace cast {
11             typedef std::map DynCastCacheMap;
12              
13             template
14 1           DynCastCacheMap& get_map () {
15             thread_local DynCastCacheMap* map;
16 1 50         if (!map) {
17 1 50         thread_local DynCastCacheMap _map;
18 1           map = &_map;
19             }
20 1           return *map;
21             }
22              
23             constexpr const ptrdiff_t INCORRECT_PTRDIFF = PTRDIFF_MAX;
24             }}
25              
26             template
27 2           DERIVED_PTR dyn_cast (BASE* obj) {
28             using namespace detail::cast;
29             using DERIVED = typename std::remove_pointer::type;
30              
31             if (std::is_same::value) return (DERIVED_PTR)((void*)obj);
32 1 50         if (!obj) return NULL;
33              
34 1 50         intptr_t key = (intptr_t)typeid(*obj).name();
35 1           auto& map = get_map();
36             //auto& map = DynCastCache::map;
37 1 50         DynCastCacheMap::iterator it = map.find(key);
38 1 50         if (it != map.end())
39 0 0         return it->second != INCORRECT_PTRDIFF ? reinterpret_cast((char*)obj - it->second) : NULL;
40 1 50         DERIVED* ret = dynamic_cast(obj);
41 1 50         if (ret) map[key] = (char*)obj - (char*)ret;
    50          
42 0 0         else map[key] = INCORRECT_PTRDIFF;
43 1           return ret;
44             }
45              
46             template
47             DERIVED_REF dyn_cast (BASE& obj) {
48             using namespace detail::cast;
49             using DERIVED = typename std::remove_reference::type;
50              
51             if (std::is_same::value) return reinterpret_cast(obj);
52              
53             intptr_t key = (intptr_t)typeid(obj).name();
54             auto& map = get_map();
55             DynCastCacheMap::iterator it = map.find(key);
56             if (it != map.end() && it->second != INCORRECT_PTRDIFF)
57             return *(reinterpret_cast((char*)&obj - it->second));
58             // dont cache fails, as exceptions are much slower than dynamic_cast, let it always fall here
59             DERIVED& ret = dynamic_cast(obj);
60             map[key] = (char*)&obj - (char*)&ret;
61             return ret;
62             }
63              
64             }