File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/XS/Framework.x/i/xs/Stash.h
Criterion Covered Total %
statement 16 20 80.0
branch 12 54 22.2
condition n/a
subroutine n/a
pod n/a
total 28 74 37.8


line stmt bran cond sub pod time code
1             #pragma once
2             #include
3             #include
4             #include
5             #include
6             #include
7             #include
8             #include
9             #include
10              
11             namespace xs {
12              
13             using xs::my_perl;
14              
15 1122           struct Stash : Hash {
16             using string_view = panda::string_view;
17              
18             struct op_proxy : Glob {
19             op_proxy (SV** ptr) : Glob(), ptr(ptr) { if (ptr) set(*ptr); }
20             op_proxy (const op_proxy&) = default;
21             op_proxy (op_proxy&&) = default;
22              
23             op_proxy& operator= (SV*);
24             op_proxy& operator= (AV* v) { _throw(); slot(v); return *this; }
25             op_proxy& operator= (HV* v) { _throw(); slot(v); return *this; }
26             op_proxy& operator= (CV* v) { _throw(); slot(v); return *this; }
27             op_proxy& operator= (IO* v) { _throw(); slot(v); return *this; }
28             op_proxy& operator= (GV*);
29             op_proxy& operator= (std::nullptr_t) { return operator=((SV*)NULL); }
30             op_proxy& operator= (const Sv& v) { return operator=(v.get()); }
31             op_proxy& operator= (const Scalar& v) { _throw(); slot(v); return *this; }
32             op_proxy& operator= (const Array& v) { _throw(); slot(v); return *this; }
33             op_proxy& operator= (const Hash& v) { _throw(); slot(v); return *this; }
34             op_proxy& operator= (const Sub& v) { _throw(); slot(v); return *this; }
35             op_proxy& operator= (const Io& v) { _throw(); slot(v); return *this; }
36             op_proxy& operator= (const Glob& v) { return operator=(v.get()); }
37             op_proxy& operator= (const op_proxy& v) { return operator=(v.get()); }
38              
39             inline void _throw () { if (!ptr) throw std::logic_error("store: empty object"); }
40              
41             private:
42             SV** ptr;
43             };
44              
45             static Stash root () { return PL_defstash; }
46              
47             static Stash from_name (SV* fqn, I32 flags = 0) { return gv_stashsv(fqn, flags); }
48              
49 402           Stash (std::nullptr_t = nullptr) {}
50             Stash (SV* sv, bool policy = INCREMENT) : Hash(sv, policy) { _validate(); }
51 0 0         Stash (HV* sv, bool policy = INCREMENT) : Hash(sv, policy) { _validate(); }
52              
53 212           Stash (const string_view& package, I32 flags = 0) {
54 106 50         *this = gv_stashpvn(package.data(), package.length(), flags);
    50          
55 106           }
56              
57 418           Stash (const Stash& oth) : Hash(oth) {}
58             Stash (const Hash& oth) : Hash(oth) { _validate(); }
59             Stash (const Sv& oth) : Stash(oth.get()) {}
60             Stash (Stash&& oth) : Hash(std::move(oth)) {}
61             Stash (Hash&& oth) : Hash(std::move(oth)) { _validate(); }
62             Stash (Sv&& oth) : Hash(std::move(oth)) { _validate(); }
63              
64             Stash (const Simple&) = delete;
65             Stash (const Array&) = delete;
66             Stash (const Sub&) = delete;
67             Stash (const Glob&) = delete;
68             Stash (const Io&) = delete;
69              
70             Stash& operator= (SV* val) { Hash::operator=(val); _validate(); return *this; }
71 590           Stash& operator= (HV* val) { Hash::operator=(val); _validate(); return *this; }
72             Stash& operator= (std::nullptr_t) { Hash::operator=(nullptr); return *this; }
73             Stash& operator= (const Stash& oth) { Hash::operator=(oth); return *this; }
74 24           Stash& operator= (Stash&& oth) { Hash::operator=(std::move(oth)); return *this; }
75             Stash& operator= (const Hash& oth) { Hash::operator=(oth); _validate(); return *this; }
76             Stash& operator= (Hash&& oth) { Hash::operator=(std::move(oth)); _validate(); return *this; }
77             Stash& operator= (const Sv& oth) { return operator=(oth.get()); }
78             Stash& operator= (Sv&& oth) { Hash::operator=(std::move(oth)); _validate(); return *this; }
79             Stash& operator= (const Simple&) = delete;
80             Stash& operator= (const Array&) = delete;
81             Stash& operator= (const Sub&) = delete;
82             Stash& operator= (const Glob&) = delete;
83             Stash& operator= (const Io&) = delete;
84              
85             using Hash::set;
86             void set (HV* val) { Hash::operator=(val); }
87              
88 33           Glob fetch (const string_view& key) const {
89 66 50         auto elem = Hash::fetch(key);
90 33 50         _promote(elem.get(), key);
91 66 50         return elem.get();
92             }
93              
94             Glob at (const string_view& key) const {
95             Glob ret = fetch(key);
96             if (!ret) throw std::out_of_range("at: no key");
97             return ret;
98             }
99              
100             Glob operator[] (const string_view& key) const { return fetch(key); }
101              
102             void store (const string_view& key, SV* v) { operator[](key) = v; }
103             void store (const string_view& key, AV* v) { operator[](key) = v; }
104             void store (const string_view& key, HV* v) { operator[](key) = v; }
105             void store (const string_view& key, CV* v) { operator[](key) = v; }
106             void store (const string_view& key, GV* v) { operator[](key) = v; }
107             void store (const string_view& key, const Sv& v) { operator[](key) = v; }
108             void store (const string_view& key, const Scalar& v) { operator[](key) = v; }
109             void store (const string_view& key, const Array& v) { operator[](key) = v; }
110             void store (const string_view& key, const Hash& v) { operator[](key) = v; }
111             void store (const string_view& key, const Sub& v) { operator[](key) = v; }
112             void store (const string_view& key, const Io& v) { operator[](key) = v; }
113             void store (const string_view& key, const Glob& v) { operator[](key) = v; }
114              
115             op_proxy operator[] (const string_view& key) {
116             if (!sv) return NULL;
117             SV** ref = hv_fetch((HV*)sv, key.data(), key.length(), 1);
118             _promote((GV*)*ref, key);
119             return ref;
120             }
121              
122 0 0         string_view name () const { return string_view(HvNAME(sv), HvNAMELEN(sv)); }
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
123             HEK* name_hek () const { return HvNAME_HEK_NN((HV*)sv); }
124             const Simple& name_sv () const { if (!_name_sv) _name_sv = Simple::shared(name_hek()); return _name_sv; }
125             string_view effective_name () const { return string_view(HvENAME(sv), HvENAMELEN(sv)); }
126             panda::string path () const;
127              
128             Scalar scalar (const string_view& name) const { return fetch(name).scalar(); }
129             Array array (const string_view& name) const { return fetch(name).array(); }
130             Hash hash (const string_view& name) const { return fetch(name).hash(); }
131             Sub sub (const string_view& name) const { return fetch(name).sub(); }
132             Io io (const string_view& name) const { return fetch(name).io(); }
133              
134             void scalar (const string_view& name, const Scalar& v) { operator[](name) = v; }
135             void array (const string_view& name, const Array& v) { operator[](name) = v; }
136             void hash (const string_view& name, const Hash& v) { operator[](name) = v; }
137             void sub (const string_view& name, const Sub& v) { operator[](name) = v; }
138             void io (const string_view& name, const Io& v) { operator[](name) = v; }
139              
140             Sub method (const Sv& name) const {
141             GV* gv = gv_fetchmeth_sv((HV*)sv, name, 0, 0);
142             return gv ? Sub(GvCV(gv)) : Sub();
143             }
144              
145             Sub method (const string_view& name) const {
146             GV* gv = gv_fetchmeth_pvn((HV*)sv, name.data(), name.length(), 0, 0);
147             return gv ? Sub(GvCV(gv)) : Sub();
148             }
149              
150             Sub method_strict (const Sv& name) const {
151             Sub ret = method(name);
152             if (!ret) _throw_nomethod(name);
153             return ret;
154             }
155              
156             Sub method_strict (const string_view& name) const {
157             Sub ret = method(name);
158             if (!ret) _throw_nomethod(name);
159             return ret;
160             }
161              
162             Sub next_method (const Sub& current) const { return xs::next::method((HV*)sv, current.get()); }
163             Sub next_method_strict (const Sub& current) const { return xs::next::method_strict((HV*)sv, current.get()); }
164              
165             Sub super_method (const Sub& current) const { return xs::super::method((HV*)sv, current.get()); }
166             Sub super_method_strict (const Sub& current) const { return xs::super::method_strict((HV*)sv, current.get()); }
167              
168             void mark_as_loaded (const Stash& source) const;
169             void mark_as_loaded (const string_view& source) const { mark_as_loaded(Stash(source, GV_ADD)); }
170              
171             void inherit (const Stash& parent);
172             void inherit (const string_view& parent) { inherit(Stash(parent, GV_ADD)); }
173              
174             bool isa (const string_view& parent, U32 hash = 0, int flags = 0) const;
175             bool isa (HEK* hek) const { return isa(string_view(HEK_KEY(hek), HEK_LEN(hek)), HEK_HASH(hek), HEK_UTF8(hek)); }
176             bool isa (const Stash& parent) const { return isa(HvNAME_HEK(parent.get())); }
177              
178             template Sub::call_t call (const Sv& name, A&&...args) const { return method_strict(name).call(name_sv(), std::forward(args)...); }
179             template Sub::call_t call (string_view name, A&&...args) const { return method_strict(name).call(name_sv(), std::forward(args)...); }
180             template Sub::call_t call_SUPER (const Sub& ctx, A&&...args) const { return ctx.SUPER_strict().call(name_sv(), std::forward(args)...); }
181             template Sub::call_t call_next (const Sub& ctx, A&&...args) const { return next_method_strict(ctx).call(name_sv(), std::forward(args)...); }
182             template Sub::call_t call_super (const Sub& ctx, A&&...args) const { return super_method_strict(ctx).call(name_sv(), std::forward(args)...); }
183              
184             template
185             Sub::call_t call_next_maybe (const Sub& ctx, A&&...args) const {
186             auto sub = next_method(ctx);
187             if (!sub) return Sub::call_t();
188             return sub.call(name_sv(), std::forward(args)...);
189             }
190              
191             template
192             Sub::call_t call_super_maybe (const Sub& ctx, A&&...args) const {
193             auto sub = super_method(ctx);
194             if (!sub) return Sub::call_t();
195             return sub.call(name_sv(), std::forward(args)...);
196             }
197              
198             Object bless () const;
199             Object bless (const Sv& what) const;
200              
201             void add_const_sub (const panda::string_view& name, const Sv& val);
202              
203             private:
204             mutable Simple _name_sv;
205              
206 295           void _validate () {
207 295 50         if (!sv) return;
208 295 50         if (HvNAME(sv)) return;
    50          
    50          
    50          
    50          
    50          
209 0 0         if (is_undef()) return reset();
210 0           reset();
211 295 0         throw std::invalid_argument("SV is not a Stash or Stash reference");
212             }
213              
214             void _promote (GV* gv, const panda::string_view& key) const;
215              
216             void _throw_nomethod (const panda::string_view&) const;
217              
218             void _throw_nomethod (const Sv& name) const {
219             panda::string_view _name = Simple(name);
220             _throw_nomethod(_name);
221             }
222             };
223              
224             }