File Coverage

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


line stmt bran cond sub pod time code
1             #pragma once
2             #include
3             #include
4             #include
5             #include
6             #include
7             #include
8              
9             namespace xs {
10              
11 0           struct Hash : Sv {
12 216060           static Hash create () { return Hash(newHV(), NONE); }
13              
14             static Hash create (size_t cap) {
15             auto ret = create();
16             ret.reserve(cap);
17             return ret;
18             }
19              
20             static Hash create (const std::initializer_list>& l) { return Hash(l); }
21              
22             static Hash noinc (SV* val) { return Hash(val, NONE); }
23             static Hash noinc (HV* val) { return Hash(val, NONE); }
24              
25 2456           Hash (std::nullptr_t = nullptr) {}
26             Hash (SV* sv, bool policy = INCREMENT) : Sv(sv, policy) { _validate(); }
27 216060           Hash (HV* sv, bool policy = INCREMENT) : Sv(sv, policy) {}
28              
29             Hash (const Hash& oth) : Sv(oth) {}
30             Hash (Hash&& oth) : Sv(std::move(oth)) {}
31             Hash (const Sv& oth) : Hash(oth.get()) {}
32             Hash (Sv&& oth) : Sv(std::move(oth)) { _validate(); }
33              
34             Hash (const Simple&) = delete;
35             Hash (const Array&) = delete;
36             Hash (const Sub&) = delete;
37             Hash (const Glob&) = delete;
38             Hash (const Io&) = delete;
39              
40             Hash (const std::initializer_list>&);
41              
42             Hash& operator= (SV* val) { Sv::operator=(val); _validate(); return *this; }
43             Hash& operator= (HV* val) { Sv::operator=(val); return *this; }
44             Hash& operator= (const Hash& oth) { Sv::operator=(oth); return *this; }
45 2456           Hash& operator= (Hash&& oth) { Sv::operator=(std::move(oth)); return *this; }
46             Hash& operator= (const Sv& oth) { return operator=(oth.get()); }
47             Hash& operator= (Sv&& oth) { Sv::operator=(std::move(oth)); _validate(); return *this; }
48             Hash& operator= (const Simple&) = delete;
49             Hash& operator= (const Array&) = delete;
50             Hash& operator= (const Sub&) = delete;
51             Hash& operator= (const Glob&) = delete;
52             Hash& operator= (const Io&) = delete;
53              
54             void set (SV* val) { Sv::operator=(val); }
55              
56             operator AV* () const = delete;
57             operator HV* () const { return (HV*)sv; }
58             operator CV* () const = delete;
59             operator GV* () const = delete;
60             operator IO* () const = delete;
61              
62             HV* operator-> () const { return (HV*)sv; }
63              
64             template panda::enable_if_one_of_t* get () const { return (T*)sv; }
65              
66             Scalar fetch (const panda::string_view& key) const {
67             if (!sv) return Scalar();
68             SV** ref = hv_fetch((HV*)sv, key.data(), key.length(), 0);
69             Scalar ret;
70             if (ref) ret.set(*ref);
71             return ret;
72             }
73              
74             Scalar at (const panda::string_view& key) const {
75             Scalar ret = fetch(key);
76             if (!ret) throw std::out_of_range("at: no key");
77             return ret;
78             }
79              
80             Scalar operator[] (const panda::string_view& key) const { return fetch(key); }
81              
82             void store (const panda::string_view& key, const Scalar& val, U32 hash = 0);
83             void store (const panda::string_view& key, std::nullptr_t, U32 hash = 0) { store(key, Scalar(), hash); }
84             void store (const panda::string_view& key, SV* v, U32 hash = 0) { store(key, Scalar(v), hash); }
85             void store (const panda::string_view& key, const Sv& v, U32 hash = 0) { store(key, Scalar(v), hash); }
86             void store (const panda::string_view& key, const Array&, U32 hash = 0) = delete;
87             void store (const panda::string_view& key, const Hash&, U32 hash = 0) = delete;
88             void store (const panda::string_view& key, const Sub&, U32 hash = 0) = delete;
89             void store (const panda::string_view& key, const Io&, U32 hash = 0) = delete;
90              
91             KeyProxy operator[] (const panda::string_view& key) { return KeyProxy(hv_fetch((HV*)sv, key.data(), key.length(), 1), false); }
92              
93             Scalar erase (const panda::string_view& key) {
94             Scalar ret;
95             ret.set(hv_delete((HV*)sv, key.data(), key.length(), 0));
96             return ret;
97             }
98              
99             bool contains (const panda::string_view& key) const { return exists(key); }
100             bool exists (const panda::string_view& key) const {
101             if (!sv) return false;
102             return hv_exists((HV*)sv, key.data(), key.length());
103             }
104              
105             size_t size () const { return sv ? HvUSEDKEYS(sv) : 0; }
106             size_t capacity () const { return sv ? HvMAX(sv)+1 : 0; }
107              
108             void reserve (size_t newcap) { hv_ksplit((HV*)sv, newcap); }
109              
110             void undef () { if (sv) hv_undef((HV*)sv); }
111             void clear () { if (sv) hv_clear((HV*)sv); }
112              
113             struct const_iterator : private std::iterator {
114             const_iterator () : arr(NULL), end(NULL), cur(HashEntry()) {}
115              
116             const_iterator (HV* hv) : arr(HvARRAY(hv)), end(arr + HvMAX(hv) + 1), cur(HashEntry()) {
117             if (HvUSEDKEYS(hv)) operator++();
118             }
119              
120             const_iterator (const const_iterator& oth) : arr(oth.arr), end(oth.end), cur(oth.cur) {}
121              
122             const_iterator& operator++ () {
123             if (cur) {
124             cur = HeNEXT(cur);
125             if (cur) return *this;
126             }
127             while (!cur && arr != end) cur = *arr++;
128             return *this;
129             }
130              
131             const_iterator operator++ (int) {
132             const_iterator ret = *this;
133             operator++();
134             return ret;
135             }
136              
137             bool operator== (const const_iterator& oth) const { return cur == oth.cur; }
138             bool operator!= (const const_iterator& oth) const { return cur != oth.cur; }
139              
140             const HashEntry* operator-> () { return &cur; }
141             const HashEntry& operator* () { return cur; }
142              
143             const_iterator& operator= (const const_iterator& oth) {
144             arr = oth.arr;
145             end = oth.end;
146             cur = oth.cur;
147             return *this;
148             }
149              
150             protected:
151             HE** arr;
152             HE** end;
153             HashEntry cur;
154             };
155              
156             struct iterator : private std::iterator, const_iterator {
157             using const_iterator::const_iterator;
158             HashEntry* operator-> () { return &cur; }
159             HashEntry& operator* () { return cur; }
160             };
161              
162             const_iterator cbegin () const { return sv ? const_iterator((HV*)sv) : const_iterator(); }
163             const_iterator cend () const { return const_iterator(); }
164             const_iterator begin () const { return cbegin(); }
165             const_iterator end () const { return cend(); }
166             iterator begin () { return sv ? iterator((HV*)sv) : iterator(); }
167             iterator end () { return iterator(); }
168              
169             U32 push_on_stack (SV** sp) const;
170              
171             private:
172             void _validate () {
173             if (!sv) return;
174             if (SvTYPE(sv) == SVt_PVHV) return;
175             if (SvROK(sv)) { // reference to hash?
176             SV* val = SvRV(sv);
177             if (SvTYPE(val) == SVt_PVHV) {
178             Sv::operator=(val);
179             return;
180             }
181             }
182             if (is_undef()) return reset();
183             reset();
184             throw std::invalid_argument("SV is not a Hash or Hash reference");
185             }
186             };
187              
188             }
189              
190             // DEPRECATED, will be removed, use Hash.begin()/end() instead
191             #define XS_HV_ITER(hv,code) { \
192             STRLEN hvmax = HvMAX(hv); \
193             HE** hvarr = HvARRAY(hv); \
194             if (HvUSEDKEYS(hv)) \
195             for (STRLEN bucket_num = 0; bucket_num <= hvmax; ++bucket_num) \
196             for (const HE* he = hvarr[bucket_num]; he; he = HeNEXT(he)) { code } \
197             }
198             #define XS_HV_ITER_NU(hv,code) XS_HV_ITER(hv,{if(!SvOK(HeVAL(he))) continue; code})