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