File Coverage

src/xs/export.cc
Criterion Covered Total %
statement 52 64 81.2
branch 84 194 43.3
condition n/a
subroutine n/a
pod n/a
total 136 258 52.7


line stmt bran cond sub pod time code
1             #include "export.h"
2             #include
3             #include
4             #include
5              
6             namespace xs { namespace exp {
7              
8             using panda::string;
9             using panda::string_view;
10              
11 3 50         static PERL_THREAD_LOCAL struct {
12             Hash clists;
13             Stash self_stash = Stash("Export::XS", GV_ADD);
14 3           } tls;
15              
16 3           static bool _init () {
17 12 50         xs::at_perl_destroy([]{
18 3           tls.clists = nullptr;
19 3           tls.self_stash = nullptr;
20 6 50         });
21 3           return true;
22             }
23 3           static bool __init = _init();
24              
25 0 0         static void throw_noname (Stash s) { throw std::logic_error(string("Export::XS: can't define a constant with an empty name in '") + s.name() + "'"); }
    0          
    0          
    0          
26              
27 10           Array constants_list (const Stash& stash) {
28 10 100         if (!tls.clists) tls.clists = Hash::create();
    50          
29 20 50         auto clist = tls.clists[stash.name()];
30 10 100         if (!clist.defined()) clist = Ref::create(Array::create());
    50          
    50          
    50          
31 20 50         return Array(clist);
32             }
33              
34 17           static void register_export_impl (const Stash& stash, string_view name, Array clist) {
35 17 50         if (!name.length()) throw_noname(stash);
    0          
36 17 50         if (!clist) clist = constants_list(stash);
37 17 50         clist.push(Simple(name));
38 17           }
39              
40 0           void register_export (const Stash& stash, string_view name) {
41 0 0         register_export_impl(stash, name, {});
42 0           }
43              
44 18           static void create_constant_impl (Stash& stash, const Constant& c, Array clist) {
45 18 50         if (!c.name.length()) throw_noname(stash);
    0          
46              
47             // check that we won't redefine any subroutine
48 18 100         if (stash.sub(c.name)) throw std::logic_error(string("Export::XS: can't create constant '") + stash.name() + "::" + c.name + "' - symbol already exists");
    50          
    50          
    50          
    50          
    50          
    50          
49              
50 17           stash.add_const_sub(c.name, c.value);
51 17 50         register_export_impl(stash, c.name, clist);
52 17           }
53              
54 0           void create_constant (Stash stash, const Constant& c) {
55 0 0         create_constant_impl(stash, c, {});
56 0           }
57              
58 0           void create_constants (Stash stash, const std::initializer_list& list) {
59 0 0         auto clist = constants_list(stash);
60 0 0         for (auto& c : list) create_constant_impl(stash, c, clist);
    0          
    0          
61 0           }
62              
63 3           void create_constants (Stash stash, const Hash& hash) {
64 6 50         auto clist = constants_list(stash);
65 15 50         for (const auto& row : hash) create_constant_impl(stash, Constant(row.key(), row.value()), clist);
    100          
    50          
    50          
    50          
    100          
66 2           }
67              
68 4           void create_constants (Stash stash, SV*const* list, size_t items) {
69 4 50         if (!list || !items) return;
    50          
70 8 50         auto clist = constants_list(stash);
71 9 100         for (size_t i = 0; i < items - 1; i += 2) {
72 11 100         Simple name = *list++;
73 10           Sv value = *list++;
74 5 50         create_constant_impl(stash, Constant(name, value), clist);
    50          
    50          
    50          
75             }
76             }
77              
78 31           void export_sub (const Stash& from, Stash to, string_view name) {
79 62 50         auto gv = from.fetch(name);
80 31 50         if (!gv.sub()) throw std::logic_error(string("Export::XS: can't export unexisting symbol '") + from.name() + "::" + name + "'");
    100          
    50          
    50          
    50          
    50          
    50          
    50          
81 30 50         to[name] = gv; // "to[name] = sub" leads to "used once once" warning. setting the whole glob supresses the warning
    50          
82 30           }
83              
84 3           void export_constants (const Stash& from, Stash to) {
85 6 50         auto clist = constants_list(from);
86 26 50         for (const auto& elem : clist) export_sub(from, to, Simple(elem));
    50          
    100          
    50          
    50          
    50          
    50          
    50          
87 3           }
88              
89 2           void autoexport (Stash stash) {
90 4 50         auto gv = tls.self_stash["import"];
91 4 50         auto dsub = stash.sub("import");
92 2 100         if (dsub && dsub != gv.sub() && (!dsub.stash() || dsub.stash().name() != "UNIVERSAL")) {
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    0          
    0          
93 0 0         throw std::logic_error(string("Export::XS: can't make autoexport for stash '") + stash.name() + "' - you already have import() sub");
    0          
    0          
    0          
94             }
95 2 50         stash["import"] = gv;
    50          
96 2           }
97              
98 12 50         }}
    50