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 5 17 29.4
branch 2 50 4.0
condition n/a
subroutine n/a
pod n/a
total 7 67 10.4


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