File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/XS/Framework.x/i/xs/Object.h
Criterion Covered Total %
statement 21 23 91.3
branch 16 28 57.1
condition n/a
subroutine n/a
pod n/a
total 37 51 72.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 xs {
9              
10             struct Stash;
11              
12 368           struct Object : Sv {
13             using string_view = panda::string_view;
14              
15             Object (std::nullptr_t = nullptr) {}
16              
17             template >
18 111 50         Object (T* sv, bool policy = INCREMENT) : Sv(sv, policy) { _validate(); }
19              
20             Object (const Object& oth) : Sv(oth), _ref(oth._ref) {}
21             Object (Object&& oth) : Sv(std::move(oth)), _ref(std::move(oth._ref)) {}
22 0 0         Object (const Sv& oth) : Sv(oth) { _validate(); }
23 40 50         Object (Sv&& oth) : Sv(std::move(oth)) { _validate(); }
24              
25             template >
26             Object& operator= (T* val) { _ref.reset(); Sv::operator=(val); _validate(); return *this; }
27             Object& operator= (std::nullptr_t) { _ref.reset(); Sv::operator=(nullptr); return *this; }
28             Object& operator= (const Object& oth) { Sv::operator=(oth); _ref = oth._ref; return *this; }
29             Object& operator= (Object&& oth) { Sv::operator=(std::move(oth)); _ref = std::move(oth._ref); return *this; }
30             Object& operator= (const Sv& oth) { _ref.reset(); Sv::operator=(oth); _validate(); return *this; }
31             Object& operator= (Sv&& oth) { _ref.reset(); Sv::operator=(std::move(oth)); _validate(); return *this; }
32              
33             template >
34             void set (T* val) { _ref.reset(); Sv::operator=(val); }
35              
36 164           Stash stash () const { return SvSTASH(sv); }
37              
38             void stash (const Stash&);
39              
40 76           const Ref& ref () const { _check_ref(); return _ref; }
41              
42             void rebless (const Stash& stash);
43              
44             Sub method (const Sv& name) const;
45             Sub method (const string_view& name) const;
46             Sub method_strict (const Sv& name) const;
47             Sub method_strict (const string_view& name) const;
48              
49             Sub next_method (const Sub& current) const { return xs::next::method(stash(), current.get()); }
50             Sub next_method_strict (const Sub& current) const { return xs::next::method_strict(stash(), current.get()); }
51              
52             Sub super_method (const Sub& current) const { return xs::super::method(stash(), current.get()); }
53             Sub super_method_strict (const Sub& current) const { return xs::super::method_strict(stash(), current.get()); }
54              
55             bool isa (const string_view& parent) { _check_ref(); return sv_derived_from_pvn(_ref, parent.data(), parent.length(), 0); }
56             bool isa (const Stash& parent) { return isa(parent.name()); }
57              
58             template Sub::call_t call (const Sv& name, A&&...args) const { _check_ref(); return method_strict(name).call(_ref, std::forward(args)...); }
59             template Sub::call_t call (string_view name, A&&...args) const { _check_ref(); return method_strict(name).call(_ref, std::forward(args)...); }
60             template Sub::call_t call_SUPER (const Sub& ctx, A&&...args) const { return ctx.SUPER_strict().call(_ref, std::forward(args)...); }
61             template Sub::call_t call_next (const Sub& ctx, A&&...args) const { return next_method_strict(ctx).call(_ref, std::forward(args)...); }
62             template Sub::call_t call_super (const Sub& ctx, A&&...args) const { return super_method_strict(ctx).call(_ref, std::forward(args)...); }
63              
64             template
65             Sub::call_t call_next_maybe (const Sub& ctx, A&&...args) const {
66             auto sub = next_method(ctx);
67             if (!sub) return Sub::call_t();
68             return sub.call(_ref, std::forward(args)...);
69             }
70              
71             template
72             Sub::call_t call_super_maybe (const Sub& ctx, A&&...args) const {
73             auto sub = super_method(ctx);
74             if (!sub) return Sub::call_t();
75             return sub.call(_ref, std::forward(args)...);
76             }
77              
78 2           void reset () { _ref.reset(); Sv::reset(); }
79              
80 3           SV* detach () {
81 3           _ref.reset();
82 3           return Sv::detach();
83             }
84              
85             private:
86             mutable Ref _ref;
87              
88 151           void _validate () {
89 151 50         if (!sv) return;
90 151 100         if (SvOBJECT(sv)) return;
91 148 100         if (SvROK(sv)) { // reference to object?
92 147           SV* val = SvRV(sv);
93 147 50         if (SvOBJECT(val)) {
94 147 50         _ref = sv;
95 147 50         Sv::operator=(val);
96 147           return;
97             }
98             }
99 1 50         if (is_undef()) return reset();
100 0           reset();
101 151 0         throw std::invalid_argument("SV is not an Object (blessed value or reference to blessed value)");
102             }
103              
104 76 100         void _check_ref () const { if (!_ref || SvRV(_ref) != sv) _ref = Ref::create(sv); }
    50          
    100          
105             };
106              
107             }