File Coverage

xs/util.cc
Criterion Covered Total %
statement 187 208 89.9
branch 254 1064 23.8
condition n/a
subroutine n/a
pod n/a
total 441 1272 34.6


line stmt bran cond sub pod time code
1             #include "util.h"
2             #include
3             #include
4              
5             using namespace panda;
6             using namespace panda::log;
7             using panda::log::Level;
8              
9             namespace xs { namespace xlog {
10              
11             #define OP_NA (OP_max + 1)
12              
13             using backend_t = std::add_pointer::type;
14              
15             using Args = std::vector;
16             using Optimizer = std::function;
17              
18             static Sv::payload_marker_t module_cache_marker;
19              
20 97           bool has_module (SV* ref) {
21 97 100         if (SvOBJECT(ref)) {
22 92           auto stash = SvSTASH(ref);
23 92 50         return string_view(HvNAME(stash), HvNAMELEN(stash)) == "XLog::Module";
    50          
    50          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
24             }
25 97           return false;
26             }
27              
28 201           Module* get_module_by_namespace (Stash stash) {
29 201           auto module = (Module*)stash.payload(&module_cache_marker).ptr; // try to get module from cache
30 201 100         if (module) return module;
31              
32 216           Object module_obj;
33 15           auto name = stash.name();
34              
35 17           while (1) {
36 39 50         auto pkg = Stash(name);
37 32 50         if (pkg) {
38 64 50         auto val = pkg.fetch("xlog_module").scalar();
    50          
39 32 100         if (val && val.is_object_ref()) {
    100          
    100          
40 39 50         Object o = val;
    100          
41 7 50         if (o.stash().name() == "XLog::Module") {
    50          
    100          
42 6 50         module = xs::in(o);
43 6 50         module_obj = o;
44 7 100         break;
45             }
46             }
47             }
48 26 100         if (!name.length()) break; // stop after main::
49 17 50         auto pos = name.rfind("::");
50 17 100         if (pos == string_view::npos) { // look in main::
51 10           name = "";
52 10           continue;
53             }
54 32 50         name = name.substr(0, pos);
55             }
56              
57 25 100         if (!module) module = &::panda_log_module;
58 15 50         stash.payload_attach((void*)module, module_obj, &module_cache_marker);
59              
60 15           return module;
61             }
62              
63 201           Module* resolve_module(size_t depth) {
64 402           Stash stash;
65 201 100         if (depth == 0) {
66 189 50         stash = CopSTASH(PL_curcop);
67             }
68             else {
69 12           const PERL_CONTEXT *dbcx = nullptr;
70 12 50         const PERL_CONTEXT *cx = caller_cx(depth, &dbcx);
71 12 50         if (cx) {
72 12 50         if ((CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT)) {
    0          
73             #ifdef CvHASGV
74 12           bool has_gv = CvHASGV(dbcx->blk_sub.cv);
75             #else
76             GV * const cvgv = CvGV(dbcx->blk_sub.cv);
77             /* So is ccstack[dbcxix]. */
78             bool has_gv = (cvgv && isGV(cvgv));
79             #endif
80 12 50         if (has_gv) {
81 24 50         xs::Sub sub(dbcx->blk_sub.cv);
82 12 50         stash = sub.glob().effective_stash();
    50          
83 12           }
84             }
85 12 0         else stash = CopSTASH(cx->blk_oldcop);
86             }
87             }
88             // fallback
89 201 50         if (!stash) return &::panda_log_module;
90              
91 201 50         return get_module_by_namespace(stash);
    50          
92             }
93              
94              
95             template
96 103           inline static OP* pp_maybe_skip(SkipPredicate&& p) {
97 103           bool skip = true;
98             try {
99 103 0         skip = p();
    0          
    0          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    50          
    0          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    50          
    50          
100 3           } catch (panda::string& ex) {
101 3 0         croak_sv(newSVpvn_flags(ex.c_str(), ex.length(), SVf_UTF8 | SVs_TEMP));
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
102             }
103 100 0         if (skip) {
    0          
    0          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    50          
    0          
    100          
    100          
    100          
    0          
    0          
    0          
    0          
    0          
    100          
    0          
    100          
    100          
104 27           OP* cur_op = PL_op;
105 89 0         while (OpHAS_SIBLING(cur_op)) { cur_op = OpSIBLING(cur_op); }
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
    50          
    0          
    0          
    100          
    50          
    100          
    50          
    100          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
    50          
    0          
    0          
    100          
    50          
    100          
    50          
106 81 0         while (cur_op->op_type != OP_ENTERSUB) { cur_op = cur_op->op_next; }
    0          
    0          
    0          
    0          
    0          
    0          
    100          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
    0          
    100          
    100          
    100          
    0          
    0          
    0          
    0          
    0          
    100          
    0          
    100          
    100          
107 27           return cur_op->op_next;
108             } else {
109 103 0         return PL_ppaddr[PL_op->op_type](aTHX);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
110             }
111             }
112              
113 103           static bool final_check(Level level, SV* mod_sv) {
114 103           const Module* module = nullptr;
115 103 100         if (mod_sv) {
116 66 50         if (mod_sv && SvROK(mod_sv)) {
    100          
117 42           auto ref = SvRV(mod_sv);
118 42           bool ok = has_module(ref);
119 42 50         if (ok) {
120 66           module = xs::in(ref);
121             }
122             }
123             }
124 100 100         if (!module) module = resolve_module(0);
125 100           return module->level() > level;
126             }
127              
128             namespace access {
129              
130 38           SV* constsv(const OP* op) {
131 38 50         if (op->op_type == OP_CONST) return cSVOPx_sv(op);
132 0           return nullptr;
133             }
134              
135 69           SV* padsv(const OP* op) {
136 69 50         if (op->op_type == OP_PADSV) return PAD_SVl(op->op_targ);
137 0           return nullptr;
138             }
139              
140 12           SV* rv2sv(const OP* op) {
141 12 50         if (OP_TYPE_IS_OR_WAS(op, OP_RV2SV)) {
    50          
    50          
142 12           auto gvop = cUNOPx(op)->op_first;
143 12 50         if (gvop->op_type == OP_GVSV) {
144 12           auto gv = cGVOPx_gv(gvop);
145 12 50         if (SvTYPE(gv) == SVt_PVGV) {
146 12           return GvSV(gv);
147             }
148             }
149             }
150 0           return nullptr;
151             }
152              
153              
154             }
155              
156             namespace with_level {
157              
158             template struct AutoModule {
159 15           static OP* pp(pTHX) {
160 30           auto check = [&]() { return final_check(level, nullptr); };
161 15 0         return pp_maybe_skip(check);
    0          
    0          
    50          
    50          
    0          
    0          
    50          
    0          
162             }
163             };
164              
165             template struct PADSV {
166 27           static OP* pp(pTHX) {
167 27           auto check = [&]() {
168 27 0         auto sv = access::padsv(OpSIBLING(PL_op));
    0          
    0          
    50          
    50          
    0          
    0          
    50          
    0          
169 27           return final_check(level, sv);
170             };
171 27 0         return pp_maybe_skip(check);
    0          
    0          
    50          
    50          
    0          
    0          
    50          
    0          
172             }
173             };
174              
175             template struct RV2SV {
176 8           static OP* pp(pTHX) {
177 8           auto check = [&]() {
178 8           bool skip = false;
179 8 0         auto sv = access::rv2sv(OpSIBLING(PL_op));
    0          
    0          
    0          
    50          
    0          
    0          
    50          
    0          
180 8 0         if (sv) skip = final_check(level, sv);
    0          
    0          
    0          
    50          
    0          
    0          
    50          
    0          
181 8           return skip;
182             };
183 8 0         return pp_maybe_skip(check);
    0          
    0          
    0          
    50          
    0          
    0          
    50          
    0          
184             }
185             };
186              
187              
188             template