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 49 58 84.4
branch 54 102 52.9
condition n/a
subroutine n/a
pod n/a
total 103 160 64.3


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