File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/Protocol/HTTP.x/i/panda/protocol/http/Fields.h
Criterion Covered Total %
statement 0 3 0.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 0 3 0.0


line stmt bran cond sub pod time code
1             #pragma once
2             #include
3             #include
4             #include
5             #include
6             #include
7              
8             namespace panda { namespace protocol { namespace http {
9              
10             inline bool iequals (string_view a, string_view b) {
11             auto sz = a.length();
12             if (sz != b.length()) return false;
13              
14             const char* ap = a.data();
15             const char* bp = b.data();
16             size_t l = sz / 8;
17             const char* e = ap + l*8;
18             for (; ap != e; ap += 8, bp += 8) {
19             uint64_t av, bv;
20             memcpy(&av, ap, 8);
21             memcpy(&bv, bp, 8);
22             if ((av|0x2020202020202020ULL) != (bv|0x2020202020202020ULL)) return false;
23             }
24              
25             auto left = sz - l*8;
26             if (left & 4) {
27             unsigned int av, bv;
28             memcpy(&av, ap, 4);
29             memcpy(&bv, bp, 4);
30             if ((av|0x20202020) != (bv|0x20202020)) return false;
31             ap += 4;
32             bp += 4;
33             }
34              
35             if (left & 2) {
36             unsigned short av, bv;
37             memcpy(&av, ap, 2);
38             memcpy(&bv, bp, 2);
39             if ((av|0x2020) != (bv|0x2020)) return false;
40             ap += 2;
41             bp += 2;
42             }
43              
44             if (left & 1) return (*ap|0x20) == (*bp|0x20);
45              
46             return true;
47             }
48              
49             template
50 0           struct Fields {
51 0           struct Field {
52             string name;
53             T value;
54             Field (const string& k, const T& v) : name(k), value(v) {}
55              
56             bool matches (string_view key) const {
57             return CASE_SENSITIVE ? (this->name == key) : iequals(this->name, key);
58             }
59              
60             Field (const Field&) = default;
61             Field (Field&&) = default;
62             Field& operator= (const Field&) = default;
63             Field& operator= (Field&&) = default;
64             };
65             using Container = boost::container::small_vector;
66              
67             Container fields;
68              
69 0           Fields () {}
70             Fields (const Fields& fields) = default;
71             Fields (Fields&& fields) = default;
72              
73             Fields& operator= (const Fields&) = default;
74             Fields& operator= (Fields&&) = default;
75              
76             bool has (string_view key) const {
77             for (const auto& f : fields) if (f.matches(key)) return true;
78             return false;
79             }
80              
81             const T& get (string_view key, const T& defval = T()) const {
82             auto it = find(key);
83             return it == fields.cend() ? defval : it->value;
84             }
85              
86             void add (const string& key, const T& value) {
87             fields.emplace_back(key, value);
88             }
89              
90             void set (const string& key, const T& value) {
91             bool replaced = false;
92             for (auto it = fields.begin(); it != fields.end();) {
93             if (it->matches(key)) {
94             if (replaced) it = fields.erase(it);
95             else {
96             replaced = true;
97             it->name = key;
98             it->value = value;
99             ++it;
100             }
101             }
102             else ++it;
103             }
104             if (!replaced) add(key, value);
105             }
106              
107             void remove (string_view key) {
108             for (auto it = fields.cbegin(); it != fields.cend();) {
109             if (it->matches(key)) it = fields.erase(it);
110             else ++it;
111             }
112             }
113              
114             bool empty () const { return fields.empty(); }
115             size_t size () const { return fields.size(); }
116              
117             void clear () { fields.clear(); }
118              
119             typename Container::const_iterator find (string_view key) const {
120             auto end = fields.crend();
121             for (auto it = fields.crbegin(); it != end; ++it) {
122             if (it->matches(key)) return it.base()-1;
123             }
124             return fields.cend();
125             }
126              
127             typename Container::iterator find (string_view key) {
128             auto end = fields.rend();
129             for (auto it = fields.rbegin(); it != end; ++it) {
130             if (it->matches(key)) return it.base()-1;
131             }
132             return fields.end();
133             }
134              
135             auto get_multi (const string_view& key) const {
136             return fields | ::ranges::view::filter([key](const Field& f) {return f.matches(key);})
137             | ::ranges::view::transform([](const Field& f) -> const string& {return f.value; });
138             }
139              
140             typename Container::iterator begin () { return fields.begin(); }
141             typename Container::const_iterator begin () const { return fields.cbegin(); }
142             typename Container::const_iterator cbegin () const { return fields.cbegin(); }
143             typename Container::iterator end () { return fields.end(); }
144             typename Container::const_iterator end () const { return fields.cend(); }
145             typename Container::const_iterator cend () const { return fields.cend(); }
146             };
147              
148             }}}