File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/XS/Framework.x/i/xs/Array.h
Criterion Covered Total %
statement 0 5 0.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 0 5 0.0


line stmt bran cond sub pod time code
1             #pragma once
2             #include
3             #include
4              
5             namespace xs {
6              
7             using xs::my_perl;
8              
9             struct Simple;
10              
11 0           struct Array : Sv {
12             enum create_type_t { ALIAS, COPY };
13              
14 0           static Array create () { return Array(newAV(), NONE); }
15              
16             static Array create (size_t cap) {
17             Array ret(newAV(), NONE);
18             ret.reserve(cap);
19             return ret;
20             }
21              
22             static Array create (size_t size, SV** content, create_type_t type = ALIAS);
23             static Array create (const std::initializer_list& l, create_type_t type = ALIAS) { return Array(l, type); }
24             static Array create (const Array& from, create_type_t type = ALIAS) { return create(from.size(), from._svlist(), type); }
25              
26             static Array noinc (SV* val) { return Array(val, NONE); }
27             static Array noinc (AV* val) { return Array(val, NONE); }
28              
29 0           Array (std::nullptr_t = nullptr) {}
30             Array (SV* sv, bool policy = INCREMENT) : Sv(sv, policy) { _validate(); }
31 0           Array (AV* sv, bool policy = INCREMENT) : Sv(sv, policy) {}
32              
33             Array (const Array& oth) : Sv(oth) {}
34             Array (Array&& oth) : Sv(std::move(oth)) {}
35             Array (const Sv& oth) : Sv(oth) { _validate(); }
36             Array (Sv&& oth) : Sv(std::move(oth)) { _validate(); }
37             Array (const Simple&) = delete;
38             Array (const Hash&) = delete;
39             Array (const Sub&) = delete;
40             Array (const Glob&) = delete;
41             Array (const Io&) = delete;
42              
43             Array (const std::initializer_list& l, create_type_t type = ALIAS);
44              
45             Array& operator= (SV* val) { Sv::operator=(val); _validate(); return *this; }
46             Array& operator= (AV* val) { Sv::operator=(val); return *this; }
47             Array& operator= (const Array& oth) { Sv::operator=(oth); return *this; }
48 0           Array& operator= (Array&& oth) { Sv::operator=(std::move(oth)); return *this; }
49             Array& operator= (const Sv& oth) { return operator=(oth.get()); }
50             Array& operator= (Sv&& oth) { Sv::operator=(std::move(oth)); _validate(); return *this; }
51             Array& operator= (const Simple&) = delete;
52             Array& operator= (const Hash&) = delete;
53             Array& operator= (const Sub&) = delete;
54             Array& operator= (const Glob&) = delete;
55             Array& operator= (const Io&) = delete;
56              
57             void set (SV* val) { Sv::operator=(val); }
58              
59             operator AV* () const { return (AV*)sv; }
60             operator HV* () const = delete;
61             operator CV* () const = delete;
62             operator GV* () const = delete;
63             operator IO* () const = delete;
64              
65             AV* operator-> () const { return (AV*)sv; }
66              
67             template panda::enable_if_one_of_t* get () const { return (T*)sv; }
68              
69             Scalar fetch (size_t key) const {
70             if (!sv) return Scalar();
71             if (key >= _size()) return Scalar();
72             Scalar ret;
73             ret.set(_svlist()[key]);
74             return ret;
75             }
76              
77             Scalar front () const { return fetch(0); }
78             Scalar back () const { return sv && _size() ? fetch(_topi()) : Scalar(); }
79              
80             Scalar at (size_t key) const {
81             Scalar ret = fetch(key);
82             if (!ret) throw std::out_of_range("at: no key");
83             return ret;
84             }
85              
86             Scalar operator[] (size_t key) const {
87             Scalar ret;
88             ret.set(_svlist()[key]);
89             return ret;
90             }
91              
92             void store (size_t key, const Scalar& val);
93             void store (size_t key, std::nullptr_t) { store(key, Scalar()); }
94             void store (size_t key, SV* v) { store(key, Scalar(v)); }
95             void store (size_t key, const Sv& v) { store(key, Scalar(v)); }
96             void store (size_t key, const Array&) = delete;
97             void store (size_t key, const Hash&) = delete;
98             void store (size_t key, const Sub&) = delete;
99             void store (size_t key, const Io&) = delete;
100              
101             KeyProxy operator[] (size_t key) { return KeyProxy(_svlist() + key, true); }
102              
103             bool exists (size_t key) const {
104             if (key >= size()) return false;
105             return _svlist()[key];
106             }
107              
108             Scalar del (size_t key) {
109             Scalar ret = fetch(key);
110             if (ret) (*this)[key] = nullptr;
111             return ret;
112             }
113              
114             size_t size () const { return sv ? _size() : 0; }
115             size_t capacity () const { return sv ? _cap() : 0; }
116             SSize_t top_index () const { return sv ? _topi() : -1; }
117              
118             void resize (size_t newsz) { av_fill((AV*)sv, (SSize_t)newsz - 1); }
119             void reserve (size_t newcap) { av_extend((AV*)sv, (SSize_t)newcap - 1); }
120              
121             Scalar shift () {
122             if (!sv) return Scalar();
123             SV* retsv = av_shift((AV*)sv);
124             if (retsv == &PL_sv_undef) return Scalar();
125             Scalar ret;
126             ret.set(retsv);
127             SvREFCNT_dec(retsv); // because av_shift does not decrement, just transfers ownership
128             return ret;
129             }
130              
131             Scalar pop () {
132             if (!sv) return Scalar();
133             SV* retsv = av_pop((AV*)sv);
134             if (retsv == &PL_sv_undef) return Scalar();
135             Scalar ret;
136             ret.set(retsv);
137             SvREFCNT_dec(retsv); // because av_pop does not decrement, just transfers ownership
138             return ret;
139             }
140              
141             void push (const std::initializer_list& l);
142             void push (const List& l);
143             void push (const Scalar& v);
144             void push (const Array&) = delete;
145             void push (const Hash&) = delete;
146             void push (const Sub&) = delete;
147             void push (const Io&) = delete;
148             void push (SV* v) { push(Scalar(v)); }
149             void push (const Sv& v) { push(Scalar(v)); }
150              
151             void unshift (const std::initializer_list& l);
152             void unshift (const List& l);
153             void unshift (const Scalar& v);
154             void unshift (const Array&) = delete;
155             void unshift (const Hash&) = delete;
156             void unshift (const Sub&) = delete;
157             void unshift (const Io&) = delete;
158             void unshift (SV* v) { unshift(Scalar(v)); }
159             void unshift (const Sv& v) { unshift(Scalar(v)); }
160              
161             void undef () { if (sv) av_undef((AV*)sv); }
162             void clear () { if (sv) av_clear((AV*)sv); }
163              
164             struct const_iterator : private std::iterator {
165             const_iterator () : cur(nullptr) {}
166             const_iterator (SV** avfirst) : cur(avfirst) {}
167              
168             const_iterator& operator++ () { ++cur; return *this; }
169             const_iterator& operator-- () { --cur; return *this; }
170              
171             const_iterator operator++ (int) { const_iterator ret = *this; operator++(); return ret; }
172             const_iterator operator-- (int) { const_iterator ret = *this; operator--(); return ret; }
173              
174             const_iterator& operator+= (ptrdiff_t n) { cur += n; return *this; }
175             const_iterator& operator-= (ptrdiff_t n) { cur -= n; return *this; }
176              
177             bool operator== (const const_iterator& oth) const { return cur == oth.cur; }
178             bool operator!= (const const_iterator& oth) const { return cur != oth.cur; }
179              
180             const Scalar* operator-> () { return (const Scalar*)cur; }
181             const Scalar& operator* () { return *((const Scalar*)cur); }
182              
183             ptrdiff_t operator- (const const_iterator& rh) { return cur - rh.cur; }
184              
185             bool operator< (const const_iterator& rh) { return cur < rh.cur; }
186             bool operator<= (const const_iterator& rh) { return cur <= rh.cur; }
187             bool operator> (const const_iterator& rh) { return cur > rh.cur; }
188             bool operator>= (const const_iterator& rh) { return cur >= rh.cur; }
189              
190             const Scalar& operator[] (size_t key) { return *((const Scalar*)(cur+key)); }
191              
192             protected:
193             SV** cur;
194             };
195              
196             struct iterator : private std::iterator, const_iterator {
197             using const_iterator::const_iterator;
198              
199             iterator& operator++ () { const_iterator::operator++(); return *this; }
200             iterator& operator-- () { const_iterator::operator--(); return *this; }
201              
202             iterator operator++ (int) { iterator ret = *this; const_iterator::operator++(); return ret; }
203             iterator operator-- (int) { iterator ret = *this; const_iterator::operator--(); return ret; }
204              
205             iterator& operator+= (ptrdiff_t n) { const_iterator::operator+=(n); return *this; }
206             iterator& operator-= (ptrdiff_t n) { const_iterator::operator-=(n); return *this; }
207              
208             Scalar* operator-> () { return (Scalar*)cur; }
209             KeyProxy operator* () { return KeyProxy(cur, true); }
210             KeyProxy operator[] (size_t key) { return KeyProxy(cur+key, true); }
211             };
212              
213             const_iterator cbegin () const { return sv ? const_iterator(_svlist()) : const_iterator(); }
214             const_iterator cend () const { return sv ? const_iterator(_svlist()+_size()) : const_iterator(); }
215             const_iterator begin () const { return cbegin(); }
216             const_iterator end () const { return cend(); }
217             iterator begin () { return sv ? iterator(_svlist()) : iterator(); }
218             iterator end () { return sv ? iterator(_svlist()+_size()) : iterator(); }
219              
220             U32 push_on_stack (SV** sp, U32 max = 0) const;
221              
222             private:
223             inline SV** _svlist () const { return AvARRAY((AV*)sv); }
224             inline size_t _size () const { return (size_t)(_topi()+1); }
225             inline void _size (size_t i) { AvFILLp((AV*)sv) = (SSize_t)i-1; }
226             inline size_t _cap () const { return (size_t)(AvMAX((AV*)sv)+1); }
227             inline SSize_t _topi () const { return AvFILLp((AV*)sv); }
228              
229             void _validate () {
230             if (!sv) return;
231             if (SvTYPE(sv) == SVt_PVAV) return;
232             if (SvROK(sv)) { // reference to array?
233             SV* val = SvRV(sv);
234             if (SvTYPE(val) == SVt_PVAV) {
235             Sv::operator=(val);
236             return;
237             }
238             }
239             if (is_undef()) return reset();
240             reset();
241             throw std::invalid_argument("SV is not an Array or Array reference");
242             }
243             };
244              
245             inline xs::Array::const_iterator operator+ (const xs::Array::const_iterator& lh, ptrdiff_t rh) { return xs::Array::const_iterator(lh) += rh; }
246             inline xs::Array::const_iterator operator+ (ptrdiff_t lh, const xs::Array::const_iterator& rh) { return xs::Array::const_iterator(rh) += lh; }
247             inline xs::Array::const_iterator operator- (const xs::Array::const_iterator& lh, ptrdiff_t rh) { return xs::Array::const_iterator(lh) -= rh; }
248             inline xs::Array::iterator operator+ (const xs::Array::iterator& lh, ptrdiff_t rh) { return xs::Array::iterator(lh) += rh; }
249             inline xs::Array::iterator operator+ (ptrdiff_t lh, const xs::Array::iterator& rh) { return xs::Array::iterator(rh) += lh; }
250             inline xs::Array::iterator operator- (const xs::Array::iterator& lh, ptrdiff_t rh) { return xs::Array::iterator(lh) -= rh; }
251              
252             struct List : public Array {
253             List () {}
254             List (SV* sv, bool policy = INCREMENT) : Array(sv, policy) {}
255             List (AV* sv, bool policy = INCREMENT) : Array(sv, policy) {}
256              
257             List (const Array& oth) : Array(oth) {}
258             List (Array&& oth) : Array(std::move(oth)) {}
259             List (const Sv& oth) : Array(oth) {}
260             List (Sv&& oth) : Array(std::move(oth)) {}
261              
262             List (const Simple&) = delete;
263             List (const Hash&) = delete;
264             List (const Sub&) = delete;
265             List (const Glob&) = delete;
266             List (const Io&) = delete;
267              
268             List& operator= (SV* val) { Array::operator=(val); return *this; }
269             List& operator= (AV* val) { Array::operator=(val); return *this; }
270             List& operator= (const Array& oth) { Array::operator=(oth); return *this; }
271             List& operator= (Array&& oth) { Array::operator=(std::move(oth)); return *this; }
272             List& operator= (const Sv& oth) { Array::operator=(oth); return *this; }
273             List& operator= (Sv&& oth) { Array::operator=(std::move(oth)); return *this; }
274              
275             List& operator= (const Simple&) = delete;
276             List& operator= (const Hash&) = delete;
277             List& operator= (const Sub&) = delete;
278             List& operator= (const Glob&) = delete;
279             List& operator= (const Io&) = delete;
280             };
281              
282             }
283              
284             // DEPRECATED, will be removed, use Array.begin()/end() instead
285             #define XS_AV_ITER(av,code) { \
286             SV** list = AvARRAY(av); \
287             SSize_t fillp = AvFILLp(av); \
288             for (SSize_t i = 0; i <= fillp; ++i) { SV* elem = *list++; code } \
289             }
290             #define XS_AV_ITER_NE(av,code) XS_AV_ITER(av,{if(!elem) continue; code})
291             #define XS_AV_ITER_NU(av,code) XS_AV_ITER(av,{if(!elem || !SvOK(elem)) continue; code})
292