File Coverage

src/xs/catch.cc
Criterion Covered Total %
statement 29 46 63.0
branch 16 72 22.2
condition n/a
subroutine n/a
pod n/a
total 45 118 38.1


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4             #include
5             #include
6             #include
7              
8             using panda::string_view;
9              
10             namespace xs {
11              
12 36           static std::vector catch_handlers;
13 36           static std::vector exception_processors;
14              
15 87           static std::string get_type_name (const std::type_info& ti) {
16             int status;
17 87 50         char* class_name = abi::__cxa_demangle(ti.name(), NULL, NULL, &status);
18 87 50         std::string ret = "[";
19 87 50         if (status == 0) {
20 87 50         ret += class_name;
21 87           free(class_name);
22             }
23 0 0         else ret = "";
24 87 50         ret += "]";
25 87           return ret;
26             }
27              
28 229           static Sv _exc2sv_default (const Sub&) {
29 458           try { throw; }
30             catch (SV* err) { return err; }
31 8 50         catch (Sv& err) { return err; }
32 110 50         catch (const char* err) { return Simple(string_view(err)); }
    0          
33             catch (const string_view& err) { return Simple(err); }
34 24 50         catch (const panda::string& err) { return Simple(err); }
    0          
35             catch (const std::string& err) { return Simple(string_view(err.data(), err.length())); }
36 174           catch (std::exception& err) {
37             dTHX;
38 174 50         auto tn = get_type_name(typeid(err));
39 87 50         SV* errsv = newSVpv(tn.data(), 0);
40 87 50         sv_catpv(errsv, " ");
41 87 50         sv_catpv(errsv, err.what());
42 87           return Sv::noinc(errsv);
43             }
44             catch (std::exception* err) {
45   0         dTHX;
    0          
    0          
    0          
    0          
46             auto tn = get_type_name(typeid(*err));
47             SV* errsv = newSVpv(tn.data(), 0);
48             sv_catpv(errsv, " ");
49             sv_catpv(errsv, err->what());
50             return Sv::noinc(errsv);
51             }
52             catch (...) {
53   0         dTHX;
    0          
    0          
54             auto tn = get_type_name(*abi::__cxa_current_exception_type());
55             SV* errsv = newSVpv(tn.data(), 0);
56             sv_catpv(errsv, " exception");
57             return Sv::noinc(errsv);
58             }
59             return Sv();
60             }
61              
62 229           static Sv _exc2sv_impl (const Sub& context, int i) {
63 229 50         if (i < 0) return _exc2sv_default(context); // no 1 has catched the exception, apply defaults
64 0 0         if (i >= (int)catch_handlers.size()) i = catch_handlers.size() - 1;
65             try {
66 0 0         auto ret = catch_handlers[i](context);
67 0 0         if (ret) return ret;
    0          
68             }
69             catch (...) {}
70 229           return _exc2sv_impl(context, i-1);
71             }
72              
73 229           Sv _exc2sv (const Sub& context) {
74 229           auto ex_sv = _exc2sv_impl(context, catch_handlers.size() - 1);
75 229 50         for (auto& processor: exception_processors) {
76 0 0         ex_sv = processor(ex_sv, context);
77             }
78 229           return ex_sv;
79             }
80              
81 0           void add_catch_handler (CatchHandler h) {
82 0           catch_handlers.push_back(h);
83 0           }
84              
85 0           void add_catch_handler (CatchHandlerSimple h) {
86 0 0         catch_handlers.push_back([h](const Sub&) -> Sv { return h(); });
    0          
87 0           }
88              
89 0           void add_exception_processor(ExceptionProcessor f) {
90 0           exception_processors.push_back(f);
91 0           }
92              
93 0           void add_exception_processor(ExceptionProcessorSimple f) {
94 0 0         exception_processors.push_back([f](Sv& ex, const Sub&) -> Sv { return f(ex); });
    0          
95 0           }
96              
97              
98 144 50         }
    50