File Coverage

src/xs/Simple.h
Criterion Covered Total %
statement 0 2 0.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 0 2 0.0


line stmt bran cond sub pod time code
1             #pragma once
2             #include
3             #include
4             #include
5             #include
6             #include
7              
8             namespace xs {
9              
10             using xs::my_perl;
11              
12             namespace detail {
13             template inline SV* _newnum (T val, panda::enable_if_signed_integral_t* = nullptr) { return newSViv(val); }
14             template inline SV* _newnum (T val, panda::enable_if_unsigned_integral_t* = nullptr) { return newSVuv(val); }
15             template inline SV* _newnum (T val, panda::enable_if_floatp_t* = nullptr) { return newSVnv(val); }
16              
17             template inline panda::enable_if_signed_integral_t _getrawnum (const SV* sv) { return SvIVX(sv); }
18             template inline panda::enable_if_unsigned_integral_t _getrawnum (const SV* sv) { return SvUVX(sv); }
19             template inline panda::enable_if_floatp_t _getrawnum (const SV* sv) { return SvNVX(sv); }
20              
21             template inline panda::enable_if_signed_integral_t _getnum (SV* sv) { return SvIV_nomg(sv); }
22             template inline panda::enable_if_unsigned_integral_t _getnum (SV* sv) { return SvUV_nomg(sv); }
23             template inline panda::enable_if_floatp_t _getnum (SV* sv) { return SvNV_nomg(sv); }
24              
25             template inline void _setrawnum (SV* sv, T val, panda::enable_if_signed_integral_t* = nullptr) { SvIV_set(sv, val); }
26             template inline void _setrawnum (SV* sv, T val, panda::enable_if_unsigned_integral_t* = nullptr) { SvUV_set(sv, val); }
27             template inline void _setrawnum (SV* sv, T val, panda::enable_if_floatp_t* = nullptr) { SvNV_set(sv, val); }
28              
29             template inline void _setnum (SV* sv, T val, panda::enable_if_signed_integral_t* = nullptr) { sv_setiv(sv, val); }
30             template inline void _setnum (SV* sv, T val, panda::enable_if_unsigned_integral_t* = nullptr) { sv_setuv(sv, val); }
31             template inline void _setnum (SV* sv, T val, panda::enable_if_floatp_t* = nullptr) { sv_setnv(sv, val); }
32             }
33              
34 0           struct Simple : Scalar {
35             static const Simple undef;
36             static const Simple yes;
37             static const Simple no;
38              
39             static Simple create (size_t capacity) {
40             SV* sv = newSV(capacity+1);
41             SvPOK_on(sv);
42             SvCUR_set(sv, 0);
43             return Simple(sv, NONE);
44             }
45              
46             static Simple shared (HEK* k) { return noinc(newSVhek(k)); }
47             static Simple shared (const panda::string_view& s, U32 hash = 0) { return noinc(newSVpvn_share(s.data(), s.length(), hash)); }
48              
49             static Simple format (const char*const pat, ...);
50              
51 0           Simple (std::nullptr_t = nullptr) {}
52              
53             Simple (SV* sv, bool policy = INCREMENT) : Scalar(sv, policy) { _validate(); }
54              
55             Simple (const Simple& oth) : Scalar(oth) {}
56             Simple (Simple&& oth) : Scalar(std::move(oth)) {}
57             Simple (const Scalar& oth) : Scalar(oth) { _validate(); }
58             Simple (Scalar&& oth) : Scalar(std::move(oth)) { _validate(); }
59             Simple (const Sv& oth) : Simple(oth.get()) {}
60             Simple (Sv&& oth) : Scalar(std::move(oth)) { _validate(); }
61              
62             Simple (const Ref&) = delete;
63             Simple (const Glob&) = delete;
64             Simple (const Array&) = delete;
65             Simple (const Hash&) = delete;
66             Simple (const Sub&) = delete;
67             Simple (const Io&) = delete;
68              
69             template >
70             explicit
71             Simple (T val) { sv = detail::_newnum(val); }
72              
73             explicit
74             Simple (const panda::string_view& s) { sv = newSVpvn(s.data(), s.length()); }
75              
76             static Simple noinc (SV* val) { return Simple(val, NONE); }
77              
78             Simple& operator= (SV* val) {
79             Scalar::operator=(val);
80             _validate();
81             return *this;
82             }
83              
84             Simple& operator= (const Simple& oth) {
85             Scalar::operator=(oth);
86             return *this;
87             }
88              
89             Simple& operator= (Simple&& oth) {
90             Scalar::operator=(std::move(oth));
91             return *this;
92             }
93              
94             Simple& operator= (const Scalar& oth) {
95             Scalar::operator=(oth);
96             _validate();
97             return *this;
98             }
99              
100             Simple& operator= (Scalar&& oth) {
101             Scalar::operator=(std::move(oth));
102             _validate();
103             return *this;
104             }
105              
106             Simple& operator= (const Sv& oth) { return operator=(oth.get()); }
107              
108             Simple& operator= (Sv&& oth) {
109             Scalar::operator=(std::move(oth));
110             _validate();
111             return *this;
112             }
113              
114             Simple& operator= (const Ref&) = delete;
115             Simple& operator= (const Glob&) = delete;
116             Simple& operator= (const Array&) = delete;
117             Simple& operator= (const Hash&) = delete;
118             Simple& operator= (const Sub&) = delete;
119             Simple& operator= (const Io&) = delete;
120              
121             // safe setters (slower)
122             template >
123             Simple& operator= (T val) {
124             if (sv) detail::_setnum(sv, val);
125             else sv = detail::_newnum(val);
126             return *this;
127             }
128              
129             Simple& operator= (const panda::string_view& s) {
130             if (sv) sv_setpvn(sv, s.data(), s.length());
131             else sv = newSVpvn(s.data(), s.length());
132             return *this;
133             }
134              
135             template >
136             void set (T val) { detail::_setrawnum(sv, val); }
137             void set (panda::string_view s) { sv_setpvn(sv, s.data(), s.length()); }
138             void set (SV* val) { Scalar::set(val); }
139              
140             using Sv::operator bool; // otherwise, operator arithmetic_t will be in priority
141              
142             template >
143             operator T () const { return sv ? detail::_getnum(sv) : T(); }
144              
145             const char* c_str () const { return sv ? SvPV_nomg_const_nolen(sv) : NULL; }
146              
147             operator panda::string_view () const { return as_string(); }
148              
149             // unsafe getters (faster)
150             template panda::enable_if_arithmetic_t get () const { return detail::_getrawnum(sv); }
151             template panda::enable_if_one_of_t get () const { return SvPVX(sv); }
152             template panda::enable_if_one_of_t get () const { return panda::string_view(SvPVX(sv), SvCUR(sv)); }
153             template panda::enable_if_one_of_t* get () const { return sv; }
154              
155             template
156             T as_string () const {
157             if (!sv) return T();
158             STRLEN len;
159             const char* buf = SvPV_nomg(sv, len);
160             return T(buf, len);
161             }
162              
163             template >
164             char operator[] (T i) const { return SvPVX_const(sv)[i]; }
165            
166             template >
167             char& operator[] (T i) { return SvPVX(sv)[i]; }
168              
169             char at (size_t i) {
170             if (!sv) throw std::out_of_range("at: no sv");
171             STRLEN len;
172             auto buf = SvPV_const(sv, len);
173             if (i >= len) throw std::out_of_range("at: index out of bounds");
174             return buf[i];
175             }
176              
177             bool is_string () const { return sv && SvPOK(sv); }
178             bool is_shared () const { return sv && SvIsCOW_shared_hash(sv); }
179             STRLEN length () const { return SvCUR(sv); }
180             void length (STRLEN newlen) { SvCUR_set(sv, newlen); }
181             STRLEN capacity () const { return SvLEN(sv); }
182             bool utf8 () const { return SvUTF8(sv); }
183             void utf8 (bool val) { if (val) SvUTF8_on(sv); else SvUTF8_off(sv); }
184              
185             U32 hash () const;
186              
187             HEK* hek () const { return SvSHARED_HEK_FROM_PV(SvPVX_const(sv)); }
188              
189             static void __at_perl_destroy ();
190              
191             private:
192             void _validate () {
193             if (!sv) return;
194             if (SvTYPE(sv) > SVt_PVMG || SvROK(sv)) {
195             reset();
196             throw std::invalid_argument("SV is not a number or string");
197             }
198             }
199             };
200              
201             template T Scalar::as_string () const { return Simple(sv).as_string(); }
202             template T Scalar::as_number () const { return Simple(sv); }
203              
204             template > inline bool operator== (const Simple& lhs, T rhs) { return (T)lhs == rhs; }
205             template > inline bool operator== (T lhs, const Simple& rhs) { return lhs == (T)rhs; }
206             template > inline bool operator!= (const Simple& lhs, T rhs) { return (T)lhs != rhs; }
207             template > inline bool operator!= (T lhs, const Simple& rhs) { return lhs != (T)rhs; }
208             template > inline bool operator> (const Simple& lhs, T rhs) { return (T)lhs > rhs; }
209             template > inline bool operator> (T lhs, const Simple& rhs) { return lhs > (T)rhs; }
210             template > inline bool operator>= (const Simple& lhs, T rhs) { return (T)lhs >= rhs; }
211             template > inline bool operator>= (T lhs, const Simple& rhs) { return lhs >= (T)rhs; }
212             template > inline bool operator< (const Simple& lhs, T rhs) { return (T)lhs < rhs; }
213             template > inline bool operator< (T lhs, const Simple& rhs) { return lhs < (T)rhs; }
214             template > inline bool operator<= (const Simple& lhs, T rhs) { return (T)lhs <= rhs; }
215             template > inline bool operator<= (T lhs, const Simple& rhs) { return lhs <= (T)rhs; }
216              
217             inline bool operator== (const Simple& lhs, const panda::string_view& rhs) { return (panda::string_view)lhs == rhs; }
218             inline bool operator== (const panda::string_view& lhs, const Simple& rhs) { return lhs == (panda::string_view)rhs; }
219             inline bool operator!= (const Simple& lhs, const panda::string_view& rhs) { return (panda::string_view)lhs != rhs; }
220             inline bool operator!= (const panda::string_view& lhs, const Simple& rhs) { return lhs != (panda::string_view)rhs; }
221             inline bool operator> (const Simple& lhs, const panda::string_view& rhs) { return (panda::string_view)lhs > rhs; }
222             inline bool operator> (const panda::string_view& lhs, const Simple& rhs) { return lhs > (panda::string_view)rhs; }
223             inline bool operator>= (const Simple& lhs, const panda::string_view& rhs) { return (panda::string_view)lhs >= rhs; }
224             inline bool operator>= (const panda::string_view& lhs, const Simple& rhs) { return lhs >= (panda::string_view)rhs; }
225             inline bool operator< (const Simple& lhs, const panda::string_view& rhs) { return (panda::string_view)lhs < rhs; }
226             inline bool operator< (const panda::string_view& lhs, const Simple& rhs) { return lhs < (panda::string_view)rhs; }
227             inline bool operator<= (const Simple& lhs, const panda::string_view& rhs) { return (panda::string_view)lhs <= rhs; }
228             inline bool operator<= (const panda::string_view& lhs, const Simple& rhs) { return lhs <= (panda::string_view)rhs; }
229              
230             inline bool operator== (const Simple& lhs, const char* rhs) { return (panda::string_view)lhs == panda::string_view(rhs); }
231             inline bool operator== (const char* lhs, const Simple& rhs) { return panda::string_view(lhs) == (panda::string_view)rhs; }
232             inline bool operator!= (const Simple& lhs, const char* rhs) { return (panda::string_view)lhs != panda::string_view(rhs); }
233             inline bool operator!= (const char* lhs, const Simple& rhs) { return panda::string_view(lhs) != (panda::string_view)rhs; }
234             inline bool operator> (const Simple& lhs, const char* rhs) { return (panda::string_view)lhs > panda::string_view(rhs); }
235             inline bool operator> (const char* lhs, const Simple& rhs) { return panda::string_view(lhs) > (panda::string_view)rhs; }
236             inline bool operator>= (const Simple& lhs, const char* rhs) { return (panda::string_view)lhs >= panda::string_view(rhs); }
237             inline bool operator>= (const char* lhs, const Simple& rhs) { return panda::string_view(lhs) >= (panda::string_view)rhs; }
238             inline bool operator< (const Simple& lhs, const char* rhs) { return (panda::string_view)lhs < panda::string_view(rhs); }
239             inline bool operator< (const char* lhs, const Simple& rhs) { return panda::string_view(lhs) < (panda::string_view)rhs; }
240             inline bool operator<= (const Simple& lhs, const char* rhs) { return (panda::string_view)lhs <= panda::string_view(rhs); }
241             inline bool operator<= (const char* lhs, const Simple& rhs) { return panda::string_view(lhs) <= (panda::string_view)rhs; }
242              
243             inline bool operator== (const Simple& lhs, char* rhs) { return (panda::string_view)lhs == panda::string_view(rhs); }
244             inline bool operator== (char* lhs, const Simple& rhs) { return panda::string_view(lhs) == (panda::string_view)rhs; }
245             inline bool operator!= (const Simple& lhs, char* rhs) { return (panda::string_view)lhs != panda::string_view(rhs); }
246             inline bool operator!= (char* lhs, const Simple& rhs) { return panda::string_view(lhs) != (panda::string_view)rhs; }
247             inline bool operator> (const Simple& lhs, char* rhs) { return (panda::string_view)lhs > panda::string_view(rhs); }
248             inline bool operator> (char* lhs, const Simple& rhs) { return panda::string_view(lhs) > (panda::string_view)rhs; }
249             inline bool operator>= (const Simple& lhs, char* rhs) { return (panda::string_view)lhs >= panda::string_view(rhs); }
250             inline bool operator>= (char* lhs, const Simple& rhs) { return panda::string_view(lhs) >= (panda::string_view)rhs; }
251             inline bool operator< (const Simple& lhs, char* rhs) { return (panda::string_view)lhs < panda::string_view(rhs); }
252             inline bool operator< (char* lhs, const Simple& rhs) { return panda::string_view(lhs) < (panda::string_view)rhs; }
253             inline bool operator<= (const Simple& lhs, char* rhs) { return (panda::string_view)lhs <= panda::string_view(rhs); }
254             inline bool operator<= (char* lhs, const Simple& rhs) { return panda::string_view(lhs) <= (panda::string_view)rhs; }
255             }