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 3 17 17.6
branch 3 24 12.5
condition n/a
subroutine n/a
pod n/a
total 6 41 14.6


line stmt bran cond sub pod time code
1             #pragma once
2             #include <xs/Sv.h>
3             #include <xs/Sub.h>
4             #include <xs/Ref.h>
5             #include <xs/next.h>
6             #include <xs/Stash.h>
7              
8             namespace xs {
9              
10             struct Stash;
11              
12 13810           struct Object : Sv {
13             using string_view = panda::string_view;
14              
15             Object (std::nullptr_t = nullptr) {}
16              
17             template <class T, typename = enable_if_rawsv_t<T>>
18             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             Object (Sv&& oth) : Sv(std::move(oth)) { _validate(); }
24              
25             template <class T, typename = enable_if_rawsv_t<T>>
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 <class T, typename = enable_if_rawsv_t<T>>
34             void set (T* val) { _ref.reset(); Sv::operator=(val); }
35              
36             Stash stash () const { return SvSTASH(sv); }
37              
38             void stash (const Stash&);
39              
40             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<CV>()); }
50             Sub next_method_strict (const Sub& current) const { return xs::next::method_strict(stash(), current.get<CV>()); }
51              
52             Sub super_method (const Sub& current) const { return xs::super::method(stash(), current.get<CV>()); }
53             Sub super_method_strict (const Sub& current) const { return xs::super::method_strict(stash(), current.get<CV>()); }
54              
55 13810           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 <class...R, class...A> Sub::call_t<R...> call (const Sv& name, A&&...args) const { _check_ref(); return method_strict(name).call<R...>(_ref, std::forward<A>(args)...); }
59             template <class...R, class...A> Sub::call_t<R...> call (string_view name, A&&...args) const { _check_ref(); return method_strict(name).call<R...>(_ref, std::forward<A>(args)...); }
60             template <class...R, class...A> Sub::call_t<R...> call_SUPER (const Sub& ctx, A&&...args) const { return ctx.SUPER_strict().call<R...>(_ref, std::forward<A>(args)...); }
61             template <class...R, class...A> Sub::call_t<R...> call_next (const Sub& ctx, A&&...args) const { return next_method_strict(ctx).call<R...>(_ref, std::forward<A>(args)...); }
62             template <class...R, class...A> Sub::call_t<R...> call_super (const Sub& ctx, A&&...args) const { return super_method_strict(ctx).call<R...>(_ref, std::forward<A>(args)...); }
63              
64             template <class...R, class...A>
65             Sub::call_t<R...> call_next_maybe (const Sub& ctx, A&&...args) const {
66             auto sub = next_method(ctx);
67             if (!sub) return Sub::call_t<R...>();
68             return sub.call<R...>(_ref, std::forward<A>(args)...);
69             }
70              
71             template <class...R, class...A>
72             Sub::call_t<R...> call_super_maybe (const Sub& ctx, A&&...args) const {
73             auto sub = super_method(ctx);
74             if (!sub) return Sub::call_t<R...>();
75             return sub.call<R...>(_ref, std::forward<A>(args)...);
76             }
77              
78 0           void reset () { _ref.reset(); Sv::reset(); }
79              
80             SV* detach () {
81             _ref.reset();
82             return Sv::detach();
83             }
84              
85             private:
86             mutable Ref _ref;
87              
88 0           void _validate () {
89 0 0         if (!sv) return;
90 0 0         if (SvOBJECT(sv)) return;
91 0 0         if (SvROK(sv)) { // reference to object?
92 0           SV* val = SvRV(sv);
93 0 0         if (SvOBJECT(val)) {
94 0 0         _ref = sv;
95 0 0         Sv::operator=(val);
96 0           return;
97             }
98             }
99 0 0         if (is_undef()) return reset();
100 0           reset();
101 0 0         throw std::invalid_argument("SV is not an Object (blessed value or reference to blessed value)");
102             }
103              
104 13810 50         void _check_ref () const { if (!_ref || SvRV(_ref) != sv) _ref = Ref::create(sv); }
    50          
    50          
105             };
106              
107             }