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 25 25 100.0
branch 8 10 80.0
condition n/a
subroutine n/a
pod n/a
total 33 35 94.2


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