File Coverage

xs/main.xs
Criterion Covered Total %
statement 75 107 70.0
branch 75 204 36.7
condition n/a
subroutine n/a
pod n/a
total 150 311 48.2


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4             #include
5             #include
6              
7             using namespace xs;
8             using namespace xs::uri;
9             using namespace panda::uri;
10             using panda::string;
11             using panda::string_view;
12              
13 13           static std::unordered_map uri_class_map;
14             static Sv::payload_marker_t data_marker;
15              
16 272           struct XsUriData {
17 272           XsUriData () : query_cache_rev(0) {}
18              
19 5           void sync_query_hash (const URI* uri) {
20 10           Hash hash;
21 5 50         if (query_cache) {
22 0 0         hash = query_cache.value();
23 0 0         hash.clear();
24             } else {
25 5 50         hash = Hash::create();
26 5 50         query_cache = Ref::create(hash);
27             }
28              
29 5 50         auto end = uri->query().cend();
30 20 50         for (auto it = uri->query().cbegin(); it != end; ++it) hash.store(it->first, Simple(it->second));
    100          
    50          
    50          
31              
32 5 50         query_cache_rev = uri->query().rev;
33 5           }
34              
35 6           Ref query_hash (const URI* uri) {
36 6 100         if (!query_cache || query_cache_rev != uri->query().rev) sync_query_hash(uri);
    50          
    100          
37 6           return query_cache;
38             }
39              
40             private:
41             Ref query_cache;
42             uint32_t query_cache_rev;
43             };
44              
45 118           static void register_perl_scheme (const string& scheme, const string_view& perl_class) {
46 118 50         uri_class_map[scheme] = Stash(perl_class);
47 118           }
48              
49 19           Stash xs::uri::get_perl_class (const URI* uri) {
50 19 50         auto it = uri_class_map.find(uri->scheme());
51 19 100         if (it == uri_class_map.end()) return Stash();
52 19 50         else return it->second;
53             }
54              
55 136           void xs::uri::data_attach (Sv& sv) {
56 136           void* data = new XsUriData();
57 136 50         Object(sv).payload_attach(data, &data_marker);
58 136           }
59              
60 136           static int data_free (pTHX_ SV*, MAGIC* mg) {
61 136           auto data = (XsUriData*)mg->mg_ptr;
62 136 50         delete data;
63 136           return 0;
64             }
65              
66 6           static XsUriData* data_get (SV* sv) {
67 6           return (XsUriData*)Object(sv).payload(&data_marker).ptr;
68             }
69              
70 5           static void add_param (URI* uri, const string& key, const Scalar& val, bool replace = false) {
71 5 50         if (val.is_array_ref()) {
72 0 0         Array arr = val;
73 0 0         if (replace) uri->query().erase(key);
    0          
    0          
74 0 0         auto end = arr.end();
75 0 0         for (auto it = arr.begin(); it != end; ++it) {
    0          
76 0 0         if (!*it) continue;
    0          
77 0 0         uri->query().emplace(key, xs::in(*it));
    0          
    0          
    0          
78             }
79             }
80 5 100         else if (replace) uri->param(key, xs::in(val));
    50          
81 4 50         else uri->query().emplace(key, xs::in(val));
    50          
82 5           }
83              
84 2           static void hash2query (Hash& hash, Query* query) {
85 2           auto end = hash.end();
86 8 50         for (auto it = hash.begin(); it != end; ++it) {
    100          
87 12 50         string key(it->key());
88 12 50         auto val = it->value();
89 6 50         if (val.is_array_ref()) {
    100          
90 2 50         Array arr = val;
91 1 50         auto end = arr.end();
92 4 50         for (auto it = arr.begin(); it != end; ++it) {
    100          
93 3 50         if (!*it) continue;
    50          
94 3 50         query->emplace(key, xs::in(*it));
    50          
    50          
95             }
96             }
97 5 50         else query->emplace(key, xs::in(val));
    50          
98             }
99 2           }
100              
101 3           static void add_query_hash (URI* uri, Hash& hash, bool replace = false) {
102 3 100         if (replace) {
103 4           Query query;
104 2 50         hash2query(hash, &query);
105 2 50         uri->query(query);
106             }
107             else {
108 1           auto end = hash.end();
109 2 50         for (auto it = hash.begin(); it != end; ++it) add_param(uri, string(it->key()), it->value());
    100          
    50          
    50          
    50          
110             }
111 3           }
112              
113 15           static void add_query_args (URI* uri, SV** sp, I32 items, bool replace = false) {
114 15 100         if (items == 1) {
115 6 100         if (SvROK(*sp)) {
116 6 50         Hash hash = *sp;
117 3 50         if (hash) add_query_hash(uri, hash, replace);
    50          
118             }
119 3 50         else if (replace) uri->query(xs::in(*sp));
    0          
120 6 50         else uri->add_query(xs::in(*sp));
121             }
122             else {
123 9           SV** spe = sp + items;
124 12 100         for (; sp < spe; sp += 2) add_param(uri, xs::in(*sp), *(sp+1), replace);
    50          
    50          
125             }
126 15           }
127              
128             MODULE = URI::XS PACKAGE = URI::XS
129             PROTOTYPES: DISABLE
130              
131             BOOT {
132 13           data_marker.svt_free = data_free;
133            
134 52 50         xs::at_perl_destroy([]{
135 13           uri_class_map.clear();
136 26 50         });
137             }
138              
139             URIx uri (string url = string(), int flags = 0) {
140 38           RETVAL = URI::create(url, flags);
141 19 50         }
142              
143             void register_scheme (string scheme, string_view perl_class) {
144 1 50         register_perl_scheme(scheme, perl_class);
145             }
146              
147             uint64_t bench_parse (string str, int flags = 0) {
148 0           RETVAL = 0;
149 0 0         for (int i = 0; i < 1000; ++i) {
150 0 0         URI u(str, flags);
151 0           RETVAL += u.path().length();
152             }
153             }
154              
155             void test_parse (string str) {
156 0 0         auto uri = URI(str);
157 0 0         printf("scheme=%s\n", uri.scheme().c_str());
    0          
158 0 0         printf("userinfo=%s\n", uri.user_info().c_str());
    0          
159 0 0         printf("host=%s\n", uri.host().c_str());
    0          
160 0 0         printf("port=%d\n", uri.port());
161 0 0         printf("path=%s\n", uri.path().c_str());
    0          
162 0 0         printf("query=%s\n", uri.raw_query().c_str());
    0          
    0          
163 0 0         printf("fragment=%s\n", uri.fragment().c_str());
    0          
164             }
165              
166             void bench_parse_query (string str) {
167 0           URI u;
168 0 0         for (int i = 0; i < 1000; ++i) {
169 0 0         u.query_string(str);
170 0 0         u.query();
171             }
172             }
173              
174             uint64_t bench_encode_uri_component (string_view str) {
175 0           RETVAL = 0;
176 0           char dest[str.length() * 3];
177 0 0         for (int i = 0; i < 1000; ++i) {
178 0 0         encode_uri_component(str, dest);
179             }
180             }
181              
182             uint64_t bench_decode_uri_component (string_view str) {
183 0           RETVAL = 0;
184 0           char dest[str.length()];
185 0 0         for (int i = 0; i < 1000; ++i) {
186 0 0         decode_uri_component(str, dest);
187             }
188             }
189              
190             INCLUDE: encode.xsi
191             INCLUDE: URI.xsi
192             INCLUDE: schemas.xsi
193             INCLUDE: cloning.xsi