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              
39             Hash (const std::initializer_list>&);
40              
41             Hash& operator= (SV* val) { Sv::operator=(val); _validate(); return *this; }
42             Hash& operator= (HV* val) { Sv::operator=(val); return *this; }
43             Hash& operator= (const Hash& oth) { Sv::operator=(oth); return *this; }
44 2456           Hash& operator= (Hash&& oth) { Sv::operator=(std::move(oth)); return *this; }
45             Hash& operator= (const Sv& oth) { return operator=(oth.get()); }
46             Hash& operator= (Sv&& oth) { Sv::operator=(std::move(oth)); _validate(); return *this; }
47             Hash& operator= (const Simple&) = delete;
48             Hash& operator= (const Array&) = delete;
49             Hash& operator= (const Sub&) = delete;
50             Hash& operator= (const Glob&) = delete;
51              
52             void set (SV* val) { Sv::operator=(val); }
53              
54             operator AV* () const = delete;
55             operator HV* () const { return (HV*)sv; }
56             operator CV* () const = delete;
57             operator GV* () const = delete;
58              
59             HV* operator-> () const { return (HV*)sv; }
60              
61             template panda::enable_if_one_of_t* get () const { return (T*)sv; }
62              
63             Scalar fetch (const panda::string_view& key) const {
64             if (!sv) return Scalar();
65             SV** ref = hv_fetch((HV*)sv, key.data(), key.length(), 0);
66             Scalar ret;
67             if (ref) ret.set(*ref);
68             return ret;
69             }
70              
71             Scalar at (const panda::string_view& key) const {
72             Scalar ret = fetch(key);
73             if (!ret) throw std::out_of_range("at: no key");
74             return ret;
75             }
76              
77             Scalar operator[] (const panda::string_view& key) const { return fetch(key); }
78              
79             void store (const panda::string_view& key, const Scalar& val, U32 hash = 0);
80             void store (const panda::string_view& key, std::nullptr_t, U32 hash = 0) { store(key, Scalar(), hash); }
81             void store (const panda::string_view& key, SV* v, U32 hash = 0) { store(key, Scalar(v), hash); }
82             void store (const panda::string_view& key, const Sv& v, U32 hash = 0) { store(key, Scalar(v), hash); }
83             void store (const panda::string_view& key, const Array&, U32 hash = 0) = delete;
84             void store (const panda::string_view& key, const Hash&, U32 hash = 0) = delete;
85             void store (const panda::string_view& key, const Sub&, U32 hash = 0) = delete;
86              
87             KeyProxy operator[] (const panda::string_view& key) { return KeyProxy(hv_fetch((HV*)sv, key.data(), key.length(), 1), false); }
88              
89             Scalar erase (const panda::string_view& key) {
90             Scalar ret;
91             ret.set(hv_delete((HV*)sv, key.data(), key.length(), 0));
92             return ret;
93             }
94              
95             bool contains (const panda::string_view& key) const { return exists(key); }
96             bool exists (const panda::string_view& key) const {
97             if (!sv) return false;
98             return hv_exists((HV*)sv, key.data(), key.length());
99             }
100              
101             size_t size () const { return sv ? HvUSEDKEYS(sv) : 0; }
102             size_t capacity () const { return sv ? HvMAX(sv)+1 : 0; }
103              
104             void reserve (size_t newcap) { hv_ksplit((HV*)sv, newcap); }
105              
106             void undef () { if (sv) hv_undef((HV*)sv); }
107             void clear () { if (sv) hv_clear((HV*)sv); }
108              
109             class const_iterator : std::iterator {
110             public:
111             const_iterator () : arr(NULL), end(NULL), cur(HashEntry()) {}
112              
113             const_iterator (HV* hv) : arr(HvARRAY(hv)), end(arr + HvMAX(hv) + 1), cur(HashEntry()) {
114             if (HvUSEDKEYS(hv)) operator++();
115             }
116              
117             const_iterator (const const_iterator& oth) : arr(oth.arr), end(oth.end), cur(oth.cur) {}
118              
119             const_iterator& operator++ () {
120             if (cur) {
121             cur = HeNEXT(cur);
122             if (cur) return *this;
123             }
124             while (!cur && arr != end) cur = *arr++;
125             return *this;
126             }
127              
128             const_iterator operator++ (int) {
129             const_iterator ret = *this;
130             operator++();
131             return ret;
132             }
133              
134             bool operator== (const const_iterator& oth) const { return cur == oth.cur; }
135             bool operator!= (const const_iterator& oth) const { return cur != oth.cur; }
136              
137             const HashEntry* operator-> () { return &cur; }
138             const HashEntry& operator* () { return cur; }
139              
140             const_iterator& operator= (const const_iterator& oth) {
141             arr = oth.arr;
142             end = oth.end;
143             cur = oth.cur;
144             return *this;
145             }
146              
147             protected:
148             HE** arr;
149             HE** end;
150             HashEntry cur;
151             };
152              
153             class iterator : std::iterator, public const_iterator {
154             public:
155             using const_iterator::const_iterator;
156             HashEntry* operator-> () { return &cur; }
157             HashEntry& operator* () { return cur; }
158             };
159              
160             const_iterator cbegin () const { return sv ? const_iterator((HV*)sv) : const_iterator(); }
161             const_iterator cend () const { return const_iterator(); }
162             const_iterator begin () const { return cbegin(); }
163             const_iterator end () const { return cend(); }
164             iterator begin () { return sv ? iterator((HV*)sv) : iterator(); }
165             iterator end () { return iterator(); }
166              
167             U32 push_on_stack (SV** sp) const;
168              
169             private:
170             void _validate () {
171             if (!sv) return;
172             if (SvTYPE(sv) == SVt_PVHV) return;
173             if (SvROK(sv)) { // reference to hash?
174             SV* val = SvRV(sv);
175             if (SvTYPE(val) == SVt_PVHV) {
176             Sv::operator=(val);
177             return;
178             }
179             }
180             if (is_undef()) return reset();
181             reset();
182             throw std::invalid_argument("wrong SV* type for Hash");
183             }
184             };
185              
186             }
187              
188             // DEPRECATED, will be removed, use Hash.begin()/end() instead
189             #define XS_HV_ITER(hv,code) { \
190             STRLEN hvmax = HvMAX(hv); \
191             HE** hvarr = HvARRAY(hv); \
192             if (HvUSEDKEYS(hv)) \
193             for (STRLEN bucket_num = 0; bucket_num <= hvmax; ++bucket_num) \
194             for (const HE* he = hvarr[bucket_num]; he; he = HeNEXT(he)) { code } \
195             }
196             #define XS_HV_ITER_NU(hv,code) XS_HV_ITER(hv,{if(!SvOK(HeVAL(he))) continue; code})