• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

xlnt-community / xlnt / 796b5d63-faf9-48e9-946d-5f649cf3d172

05 Mar 2025 05:11AM UTC coverage: 82.27% (+0.4%) from 81.87%
796b5d63-faf9-48e9-946d-5f649cf3d172

push

circleci

web-flow
Fix workbook comparisons, cleanup of included headers (#59)

This PR does the following:
1. Fixes issue https://github.com/xlnt-community/xlnt/issues/58. Please
read the issue for detailed infos.
2. Changes / removes a few definitions of `XLNT_API(_INTERNAL)` which
were defined in the wrong places (e.g. `.cpp` file, or in the header
although the function was implemented in the header too).
3. Cleans up many unnecessary or missing headers which I found along the
way.
4. Added `operator!=` to many classes to ease such comparisons and
improve programming experience.

103 of 143 new or added lines in 20 files covered. (72.03%)

3 existing lines in 2 files now uncovered.

11554 of 14044 relevant lines covered (82.27%)

1176465.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.86
./source/packaging/ext_list.cpp
1
#include <xlnt/packaging/ext_list.hpp>
2
#include <algorithm>
3

4
#include <detail/external/include_libstudxml.hpp>
5

6
namespace {
7
// send elements straight from parser to serialiser without modification
8
// runs until the end of the current open element
9
xlnt::uri roundtrip(xml::parser &p, xml::serializer &s)
6✔
10
{
11
    xlnt::uri ext_uri;
6✔
12
    int nest_level = 0;
6✔
13
    while (nest_level > 0 || (p.peek() != xml::parser::event_type::end_element && p.peek() != xml::parser::event_type::eof))
30✔
14
    {
15
        switch (p.next())
24✔
16
        {
17
        case xml::parser::start_element: {
12✔
18
            ++nest_level;
12✔
19
            auto attribs = p.attribute_map();
12✔
20
            s.start_element(p.qname());
12✔
21
            if (nest_level == 1)
12✔
22
            {
23
                ext_uri = xlnt::uri(attribs.at(xml::qname("uri")).value);
12✔
24
            }
25
            auto current_ns = p.namespace_();
12✔
26
            p.peek(); // to look into the new namespace
12✔
27
            auto new_ns = p.namespace_(); // only before attributes?
12✔
28
            if (new_ns != current_ns)
12✔
29
            {
30
                auto pref = p.prefix();
6✔
31
                s.namespace_decl(new_ns, pref);
6✔
32
            }
6✔
33
            for (auto &ele : attribs)
36✔
34
            {
35
                s.attribute(ele.first, ele.second.value);
24✔
36
            }
37
            break;
12✔
38
        }
12✔
39
        case xml::parser::end_element: {
12✔
40
            --nest_level;
12✔
41
            s.end_element();
12✔
42
            break;
12✔
43
        }
44
        case xml::parser::start_namespace_decl: {
×
45
            s.namespace_decl(p.namespace_(), p.prefix());
×
46
            break;
×
47
        }
48
        case xml::parser::end_namespace_decl: { // nothing required here
×
49
            break;
×
50
        }
51
        case xml::parser::characters: {
×
52
            s.characters(p.value());
×
53
            break;
×
54
        }
55
        case xml::parser::eof:
×
56
            return ext_uri;
×
57
        case xml::parser::start_attribute:
×
58
        case xml::parser::end_attribute:
59
        default:
60
            break;
×
61
        }
62
    }
63
    return ext_uri;
6✔
64
}
×
65
} // namespace
66

67
namespace xlnt {
68

69
ext_list::ext::ext(xml::parser &parser, const std::string &ns)
4✔
70
{
71
    std::ostringstream serialisation_stream;
4✔
72
    xml::serializer s(serialisation_stream, "", 0);
8✔
73
    s.start_element(xml::qname(ns, "wrap")); // wrapper for the xmlns declaration
8✔
74
    s.namespace_decl(ns, "");
4✔
75
    extension_ID_ = roundtrip(parser, s);
4✔
76
    s.end_element(xml::qname(ns, "wrap"));
4✔
77
    serialised_value_ = serialisation_stream.str();
4✔
78
}
4✔
79

80
ext_list::ext::ext(const uri &ID, const std::string &serialised)
×
81
    : extension_ID_(ID), serialised_value_(serialised)
×
82
{
83
}
×
84

85
void ext_list::ext::serialise(xml::serializer &serialiser, const std::string &ns)
2✔
86
{
87
    std::istringstream ser(serialised_value_);
2✔
88
    xml::parser p(ser, "", xml::parser::receive_default);
6✔
89
    p.next_expect(xml::parser::event_type::start_element, xml::qname(ns, "wrap"));
2✔
90
    roundtrip(p, serialiser);
2✔
91
    p.next_expect(xml::parser::event_type::end_element, xml::qname(ns, "wrap"));
2✔
92
}
2✔
93

94
ext_list::ext_list(xml::parser &parser, const std::string &ns)
4✔
95
{
96
    // begin with the start element already parsed
97
    while (parser.peek() == xml::parser::start_element)
8✔
98
    {
99
        extensions_.push_back(ext(parser, ns));
4✔
100
    }
101
    // end without parsing the end element
102
}
4✔
103

104
void ext_list::serialize(xml::serializer &serialiser, const std::string &ns)
2✔
105
{
106
    serialiser.start_element(ns, "extLst");
2✔
107
    for (auto &ext : extensions_)
4✔
108
    {
109
        ext.serialise(serialiser, ns);
2✔
110
    }
111
    serialiser.end_element();
2✔
112
}
2✔
113

114
void ext_list::add_extension(const uri &ID, const std::string &element)
×
115
{
116
    extensions_.push_back(ext{ID, element});
×
117
}
×
118

119
bool ext_list::has_extension(const uri &extension_uri) const
×
120
{
121
    return extensions_.end() != std::find_if(extensions_.begin(), extensions_.end(), [&extension_uri](const ext &ext) { return extension_uri == ext.extension_ID_; });
×
122
}
123

124
const ext_list::ext &ext_list::extension(const uri &extension_uri) const
×
125
{
126
    return *std::find_if(extensions_.begin(), extensions_.end(),
×
127
        [&extension_uri](const ext &ext) { return extension_uri == ext.extension_ID_; });
×
128
}
129

130
const std::vector<ext_list::ext> &ext_list::extensions() const
×
131
{
132
    return extensions_;
×
133
}
134

135
bool ext_list::operator==(const ext_list &rhs) const
×
136
{
137
    return extensions_ == rhs.extensions_;
×
138
}
139

UNCOV
140
bool ext_list::operator!=(const ext_list &rhs) const
×
141
{
NEW
142
    return !(*this == rhs);
×
143
}
144

145
} // namespace xlnt
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc