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 5 12 41.6
branch 7 14 50.0
condition n/a
subroutine n/a
pod n/a
total 12 26 46.1


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