File Coverage

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