File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/XS/Framework.x/i/xs/Sv.h
Criterion Covered Total %
statement 18 25 72.0
branch 7 24 29.1
condition n/a
subroutine n/a
pod n/a
total 25 49 51.0


line stmt bran cond sub pod time code
1             #pragma once
2             #include "basic.h"
3             #include
4             #include
5             #include
6             #include
7              
8             namespace xs {
9              
10             struct Sv; struct Scalar; struct Simple; struct Ref; struct Array; struct Hash; struct List; struct Sub; struct Stash; struct Glob; struct Object;
11             using xs::my_perl;
12              
13             template using enable_if_sv_t = std::enable_if_t::value, R>;
14             template using enable_if_rawsv_t = std::enable_if_t::value, R>;
15              
16             struct Sv {
17             static const bool INCREMENT = true;
18             static const bool NONE = false;
19              
20             static const Sv undef;
21             static const Sv yes;
22             static const Sv no;
23              
24             typedef int (*on_svdup_t) (pTHX_ MAGIC* mg, CLONE_PARAMS* param);
25             using payload_marker_t = MGVTBL;
26              
27             struct Payload {
28             void* ptr;
29             SV* obj;
30             };
31              
32             template struct PayloadMarker {
33             PANDA_GLOBAL_MEMBER_AS_PTR(PayloadMarker, payload_marker_t, get, payload_marker_t());
34             };
35              
36             static payload_marker_t* default_marker();
37              
38             template >
39             static Sv noinc (T* val) { return Sv((SV*)val, NONE); }
40              
41             static Sv create () { return Sv(newSV(0), NONE); }
42              
43             Sv (std::nullptr_t = nullptr) : sv(nullptr) {}
44              
45             template >
46 4 0         Sv (T* sv, bool policy = INCREMENT) : sv((SV*)sv) { if (policy == INCREMENT) SvREFCNT_inc_simple_void(sv); }
    0          
    50          
    0          
    0          
    0          
47              
48             Sv (const Sv& oth) : Sv(oth.sv) {}
49 90           Sv (Sv&& oth) : sv(oth.sv) { oth.sv = nullptr; }
50              
51 0           ~Sv () { SvREFCNT_dec(sv); }
52              
53             template >
54 49           Sv& operator= (T* val) {
55 49 50         SvREFCNT_inc_simple_void(val);
56 49           auto old = sv;
57 49           sv = (SV*)val;
58 49 50         SvREFCNT_dec(old);
59 49           return *this;
60             }
61              
62             Sv& operator= (const Sv& oth) { return operator=(oth.sv); }
63              
64 48           Sv& operator= (Sv&& oth) {
65 48           std::swap(sv, oth.sv);
66 48           return *this;
67             }
68              
69             // safe getters (slower)
70 0           operator SV* () const { return sv; }
71             operator AV* () const { return is_array() ? (AV*)sv : nullptr; }
72             operator HV* () const { return is_hash() ? (HV*)sv : nullptr; }
73             operator CV* () const { return is_sub() ? (CV*)sv : nullptr; }
74             operator GV* () const { return is_glob() ? (GV*)sv : nullptr; }
75             operator void* () const { return sv; } // resolves ambiguity for passing to perl-macros-api
76              
77             // unsafe getters (faster)
78 102           template enable_if_rawsv_t* get () const { return (T*)sv; }
79              
80 0           explicit operator bool () const { return sv; }
81 240           explicit operator bool () { return sv; }
82              
83             SV* operator-> () const { return sv; }
84              
85             bool defined () const { return sv && SvOK(sv); }
86             bool is_true () const { return SvTRUE_nomg(sv); }
87             svtype type () const { return SvTYPE(sv); }
88             bool readonly () const { return SvREADONLY(sv); }
89             U32 use_count () const { return sv ? SvREFCNT(sv) : 0; }
90             bool is_scalar () const { return sv && is_scalar_unsafe(); }
91             bool is_ref () const { return sv && SvROK(sv); }
92             bool is_simple () const { return sv && SvTYPE(sv) <= SVt_PVMG && !SvROK(sv); }
93             bool is_string () const { return sv && SvPOK(sv); }
94             bool is_like_number () const { return sv && looks_like_number(sv); }
95             bool is_array () const { return sv && type() == SVt_PVAV; }
96             bool is_array_ref () const { return sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV; }
97             bool is_hash () const { return sv && type() == SVt_PVHV; }
98             bool is_hash_ref () const { return sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV; }
99             bool is_sub () const { return sv && type() == SVt_PVCV; }
100             bool is_sub_ref () const { return sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV; }
101             bool is_glob () const { return sv && type() == SVt_PVGV; }
102             bool is_object () const { return sv && SvOBJECT(sv); }
103             bool is_object_ref () const { return sv && SvROK(sv) && SvOBJECT(SvRV(sv)); }
104             bool is_stash () const { return is_hash() && HvNAME(sv); }
105              
106             void readonly (bool val) {
107             if (val) SvREADONLY_on(sv);
108             else SvREADONLY_off(sv);
109             }
110              
111             void upgrade (svtype type) {
112             if (SvREADONLY(sv)) throw "cannot upgrade readonly sv";
113             if (type > SVt_PVMG && SvOK(sv)) throw "only undefined scalars can be upgraded to something more than SVt_PVMG";
114             SvUPGRADE(sv, type);
115             }
116              
117             void dump () const { sv_dump(sv); }
118              
119             MAGIC* payload_attach (Payload p, const payload_marker_t* marker) { return payload_attach(p.ptr, p.obj, marker); }
120             MAGIC* payload_attach (void* ptr, SV* obj, const payload_marker_t* marker);
121             MAGIC* payload_attach (void* ptr, const Sv& obj, const payload_marker_t* marker) { return payload_attach(ptr, (SV*)obj, marker); }
122              
123             MAGIC* payload_attach (const Sv& obj, const payload_marker_t* marker) { return payload_attach(NULL, obj, marker); }
124             MAGIC* payload_attach (SV* obj, const payload_marker_t* marker) { return payload_attach(NULL, obj, marker); }
125             MAGIC* payload_attach (void* ptr, const payload_marker_t* marker) { return payload_attach(ptr, NULL, marker); }
126              
127             bool payload_exists (const payload_marker_t* marker) const {
128             if (type() < SVt_PVMG) return false;
129             for (MAGIC* mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) if (mg->mg_virtual == marker) return true;
130             return false;
131             }
132              
133             Payload payload (const payload_marker_t* marker) const {
134             if (type() < SVt_PVMG) return Payload();
135             for (MAGIC* mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) if (mg->mg_virtual == marker) return Payload { mg->mg_ptr, mg->mg_obj };
136             return Payload();
137             }
138              
139             int payload_detach (payload_marker_t* marker) {
140             if (type() < SVt_PVMG) return 0;
141             return sv_unmagicext(sv, PERL_MAGIC_ext, marker);
142             }
143              
144 0           void reset () {
145 0           SvREFCNT_dec(sv);
146 0           sv = nullptr;
147 0           }
148              
149 62           SV* detach () {
150 62           auto tmp = sv;
151 62           sv = nullptr;
152 62           return tmp;
153             }
154              
155             static void __at_perl_destroy ();
156              
157             protected:
158             friend void swap (Sv&, Sv&);
159              
160 10 50         inline bool is_undef() const { return (SvTYPE(sv) <= SVt_PVMG && !SvOK(sv)); }
    50          
    50          
    50          
161             inline bool is_scalar_unsafe() const { return (SvTYPE(sv) <= SVt_PVMG || SvTYPE(sv) == SVt_PVGV); }
162             SV* sv;
163             };
164              
165             inline bool operator== (const Sv& lh, const Sv& rh) { return lh.get() == rh.get(); }
166             inline bool operator!= (const Sv& lh, const Sv& rh) { return !(lh == rh); }
167              
168             template > inline bool operator== (const Sv& lh, T* rh) { return lh.get() == (SV*)rh; }
169             template > inline bool operator!= (const Sv& lh, T* rh) { return lh.get() != (SV*)rh; }
170             template > inline bool operator== (T* lh, const Sv& rh) { return rh.get() == (SV*)lh; }
171             template > inline bool operator!= (T* lh, const Sv& rh) { return rh.get() != (SV*)lh; }
172              
173             inline void swap (Sv& lh, Sv& rh) { std::swap(lh.sv, rh.sv); }
174              
175             std::ostream& operator<< (std::ostream& os, const Sv& sv);
176              
177             }