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 12 16 75.0
branch 12 52 23.0
condition n/a
subroutine n/a
pod n/a
total 24 68 35.2


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