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             #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             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             static Sv noinc (T* val) { return Sv((SV*)val, NONE); }
41              
42             static Sv create () { return Sv(newSV(0), NONE); }
43              
44             Sv (std::nullptr_t = nullptr) : sv(nullptr) {}
45              
46             template >
47 4 0         Sv (T* sv, bool policy = INCREMENT) : sv((SV*)sv) { if (policy == INCREMENT) SvREFCNT_inc_simple_void(sv); }
    0          
    50          
    0          
    0          
    0          
48              
49             Sv (const Sv& oth) : Sv(oth.sv) {}
50 90           Sv (Sv&& oth) : sv(oth.sv) { oth.sv = nullptr; }
51              
52 0           ~Sv () { SvREFCNT_dec(sv); }
53              
54             template >
55 49           Sv& operator= (T* val) {
56 49 50         SvREFCNT_inc_simple_void(val);
57 49           auto old = sv;
58 49           sv = (SV*)val;
59 49 50         SvREFCNT_dec(old);
60 49           return *this;
61             }
62              
63             Sv& operator= (const Sv& oth) { return operator=(oth.sv); }
64              
65 48           Sv& operator= (Sv&& oth) {
66 48           std::swap(sv, oth.sv);
67 48           return *this;
68             }
69              
70             // safe getters (slower)
71 0           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 102           template enable_if_rawsv_t* get () const { return (T*)sv; }
81              
82 0           explicit operator bool () const { return sv; }
83 240           explicit operator bool () { return sv; }
84              
85             SV* operator-> () const { return sv; }
86              
87             bool defined () const { return sv && SvOK(sv); }
88             bool is_true () const { return SvTRUE_nomg(sv); }
89             svtype type () const { return SvTYPE(sv); }
90             bool readonly () const { return SvREADONLY(sv); }
91             U32 use_count () const { return sv ? SvREFCNT(sv) : 0; }
92             bool is_scalar () const { return sv && is_scalar_unsafe(); }
93             bool is_ref () const { return sv && SvROK(sv); }
94             bool is_simple () const { return sv && SvTYPE(sv) <= SVt_PVMG && !SvROK(sv); }
95             bool is_string () const { return sv && SvPOK(sv); }
96             bool is_like_number () const { return sv && looks_like_number(sv); }
97             bool is_array () const { return sv && type() == SVt_PVAV; }
98             bool is_array_ref () const { return is_ref_of_type(SVt_PVAV); }
99             bool is_hash () const { return sv && type() == SVt_PVHV; }
100             bool is_hash_ref () const { return is_ref_of_type(SVt_PVHV); }
101             bool is_sub () const { return sv && type() == SVt_PVCV; }
102             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             bool is_object_ref () const { return is_ref() && SvOBJECT(SvRV(sv)); }
106             bool is_stash () const { return is_hash() && HvNAME(sv); }
107             bool is_io () const { return sv && type() == SVt_PVIO; }
108             bool is_io_ref () const { return is_ref_of_type(SVt_PVIO); }
109              
110             bool is_ref_of_type (svtype type) const { return sv && SvROK(sv) && SvTYPE(SvRV(sv)) == type; }
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             MAGIC* payload_attach (void* ptr, const Sv& obj, const payload_marker_t* marker) { return payload_attach(ptr, (SV*)obj, marker); }
128              
129             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             MAGIC* payload_attach (void* ptr, const payload_marker_t* marker) { return payload_attach(ptr, NULL, marker); }
132              
133             bool payload_exists (const payload_marker_t* marker) const {
134             if (type() < SVt_PVMG) return false;
135             for (MAGIC* mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) if (mg->mg_virtual == marker) return true;
136             return false;
137             }
138              
139             Payload payload (const payload_marker_t* marker) const {
140             if (type() < SVt_PVMG) return Payload();
141             for (MAGIC* mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) if (mg->mg_virtual == marker) return Payload { mg->mg_ptr, mg->mg_obj };
142             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 62           SV* detach () {
156 62           auto tmp = sv;
157 62           sv = nullptr;
158 62           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 10 50         inline bool is_undef() const { return (SvTYPE(sv) <= SVt_PVMG && !SvOK(sv)); }
    50          
    50          
    50          
171             inline bool is_scalar_unsafe() const { return (SvTYPE(sv) <= SVt_PVMG || SvTYPE(sv) == SVt_PVGV); }
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             }