File Coverage

src/xs/typemap/object.cc
Criterion Covered Total %
statement 34 43 79.0
branch 30 70 42.8
condition n/a
subroutine n/a
pod n/a
total 64 113 56.6


line stmt bran cond sub pod time code
1             #include "object.h"
2             #include
3             #include "error.h"
4              
5             namespace xs { namespace typemap { namespace object {
6              
7             using destroy_hook_t = bool(*)(pTHX_ SV*);
8              
9             CV* fake_dtor;
10             svt_copy_t backref_marker;
11              
12             static destroy_hook_t orig_destroy_hook;
13              
14 0           static int _backref_marker (pTHX_ SV*, MAGIC*, SV*, const char*, I32) { assert(0); return 0; } // should not be called
15              
16 5289026           static bool destroy_hook (pTHX_ SV* sv) {
17 5289026           MAGIC* mg = SvMAGIC(sv);
18 5295154 100         for (; mg; mg = mg->mg_moremagic) {
19 6135 100         if (mg->mg_virtual && mg->mg_virtual->svt_copy == backref_marker) {
    100          
20 18 100         if (mg->mg_virtual->svt_local(aTHX_ sv, mg)) return TRUE;
21             }
22             }
23 5289019 50         if (orig_destroy_hook) return orig_destroy_hook(aTHX_ sv);
24 5289019           return TRUE;
25             }
26              
27 36           void init () {
28 72 50         Stash stash("XS::Framework", GV_ADD);
29              
30 36 50         fake_dtor = newCONSTSUB(stash, "__FAKE_DTOR", newSViv(0));
    50          
31 36           backref_marker = &_backref_marker;
32              
33 36 50         if (PL_destroyhook != &Perl_sv_destroyable) orig_destroy_hook = PL_destroyhook;
34 36           PL_destroyhook = destroy_hook; // needed for correct operation of Typemap Storage MG with Backref feature enabled
35 36           }
36              
37 24           panda::string type_details(const std::type_info& ti) {
38             int status;
39 24           panda::string r;
40 24 50         char* class_name = abi::__cxa_demangle(ti.name(), nullptr, nullptr, &status);
41 24 50         if (status != 0) {
42 0 0         r += "[abi::__cxa_demangle error] ";
43 0 0         r += ti.name();
44             }
45             else {
46 24 50         r += class_name;
47 24           free(class_name);
48             }
49 24           return r;
50             }
51              
52 0           [[ noreturn ]] void _throw_no_package (const std::type_info& ti) {
53 0           panda::string exc("no default perl class defined for typemap '");
54 0 0         exc += type_details(ti);
    0          
55 0 0         exc += "', either define it or explicitly bless PROTO on output";
56 0 0         throw exc;
57             }
58              
59 24           [[ noreturn ]] void _throw_incorrect_arg(SV* arg, const std::type_info& expected, panda::string_view package) {
60             //"arg is an incorrect or corrupted object";
61 48           panda::string arg_type;
62 24 50         if (!arg) { arg_type = "NULL"; }
    0          
63             else {
64 48           Sv sv{arg};
65 24 50         if (!sv.is_object() && !sv.is_object_ref()) {
    0          
    50          
66 0 0         arg_type = "not an object";
67             }
68             else {
69 48 50         Object obj(sv);
70 24 50         arg_type = obj.stash().name();
    50          
71             }
72             }
73 48           panda::string ex_details = "cannot convert arg '";
74 24 50         ex_details += arg_type;
75 24 50         ex_details += "' to expected '";
76 24 50         ex_details += package;
77 24 50         ex_details += "' (C++ type '" + type_details(expected) + "')";
    50          
    50          
    50          
78 24 50         throw ex_details;
79             }
80              
81             }}}
82