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 14 17 82.3
branch 8 20 40.0
condition n/a
subroutine n/a
pod n/a
total 22 37 59.4


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 284           struct Object : Sv {
13             using string_view = panda::string_view;
14              
15             Object (std::nullptr_t = nullptr) {}
16              
17             template >
18 7 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 135 50         Object (const Sv& oth) : Sv(oth) { _validate(); }
23             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= (const Object& oth) { Sv::operator=(oth); _ref = oth._ref; return *this; }
28             Object& operator= (Object&& oth) { Sv::operator=(std::move(oth)); _ref = std::move(oth._ref); return *this; }
29             Object& operator= (const Sv& oth) { _ref.reset(); Sv::operator=(oth); _validate(); return *this; }
30             Object& operator= (Sv&& oth) { _ref.reset(); Sv::operator=(std::move(oth)); _validate(); return *this; }
31              
32             template >
33             void set (T* val) { _ref.reset(); Sv::operator=(val); }
34              
35 4           Stash stash () const { return SvSTASH(sv); }
36              
37             void stash (const Stash&);
38              
39             const Ref& ref () const { _check_ref(); return _ref; }
40              
41             void rebless (const Stash& stash);
42              
43             Sub method (const Sv& name) const;
44             Sub method (const string_view& name) const;
45             Sub method_strict (const Sv& name) const;
46             Sub method_strict (const string_view& name) const;
47              
48             Sub next_method (const Sub& current) const { return xs::next::method(stash(), current.get()); }
49             Sub next_method_strict (const Sub& current) const { return xs::next::method_strict(stash(), current.get()); }
50              
51             Sub super_method (const Sub& current) const { return xs::super::method(stash(), current.get()); }
52             Sub super_method_strict (const Sub& current) const { return xs::super::method_strict(stash(), current.get()); }
53              
54             bool isa (const string_view& parent) { _check_ref(); return sv_derived_from_pvn(_ref, parent.data(), parent.length(), 0); }
55             bool isa (const Stash& parent) { return isa(parent.name()); }
56              
57             template Sub::call_t call (const Sv& name, A&&...args) const { _check_ref(); return method_strict(name).call(_ref, std::forward(args)...); }
58             template Sub::call_t call (string_view name, A&&...args) const { _check_ref(); return method_strict(name).call(_ref, std::forward(args)...); }
59             template Sub::call_t call_SUPER (const Sub& ctx, A&&...args) const { return ctx.SUPER_strict().call(_ref, std::forward(args)...); }
60             template Sub::call_t call_next (const Sub& ctx, A&&...args) const { return next_method_strict(ctx).call(_ref, std::forward(args)...); }
61             template Sub::call_t call_super (const Sub& ctx, A&&...args) const { return super_method_strict(ctx).call(_ref, std::forward(args)...); }
62              
63             template
64             Sub::call_t call_next_maybe (const Sub& ctx, A&&...args) const {
65             auto sub = next_method(ctx);
66             if (!sub) return Sub::call_t();
67             return sub.call(_ref, std::forward(args)...);
68             }
69              
70             template
71             Sub::call_t call_super_maybe (const Sub& ctx, A&&...args) const {
72             auto sub = super_method(ctx);
73             if (!sub) return Sub::call_t();
74             return sub.call(_ref, std::forward(args)...);
75             }
76              
77 0           void reset () { _ref.reset(); Sv::reset(); }
78              
79             SV* detach () {
80             _ref.reset();
81             return Sv::detach();
82             }
83              
84             private:
85             mutable Ref _ref;
86              
87 142           void _validate () {
88 142 50         if (!sv) return;
89 142 50         if (SvOBJECT(sv)) return;
90 142 50         if (SvROK(sv)) { // reference to object?
91 142           SV* val = SvRV(sv);
92 142 50         if (SvOBJECT(val)) {
93 142 50         _ref = sv;
94 142 50         Sv::operator=(val);
95 142           return;
96             }
97             }
98 0 0         if (is_undef()) return reset();
99 0           reset();
100 142 0         throw std::invalid_argument("SV is not an Object (blessed value or reference to blessed value)");
101             }
102              
103             void _check_ref () const { if (!_ref || SvRV(_ref) != sv) _ref = Ref::create(sv); }
104             };
105              
106             }