GCC Code Coverage Report


Directory: ./
File: pdcom5/src/msrproto/expat_wrapper_impl.h
Date: 2023-11-12 04:06:57
Exec Total Coverage
Lines: 34 37 91.9%
Branches: 15 30 50.0%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright (C) 2021 Bjarne von Horn (vh at igh dot de)
4 *
5 * This file is part of the PdCom library.
6 *
7 * The PdCom library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * The PdCom library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with the PdCom library. If not, see <http://www.gnu.org/licenses/>.
19 *
20 *****************************************************************************/
21
22 #ifndef MSRPROTO_EXPAT_WRAPPER_IMPL_H
23 #define MSRPROTO_EXPAT_WRAPPER_IMPL_H
24
25 #include "expat_wrapper.h"
26
27 #include <expat.h>
28 #include <expat_external.h>
29 #include <pdcom5/Exception.h>
30 #include <stdexcept>
31
32 namespace PdCom { namespace impl { namespace MsrProto {
33 131 inline void XmlParserDeleter::operator()(XML_ParserStruct *s) noexcept
34 {
35
1/2
✓ Branch 0 taken 131 times.
✗ Branch 1 not taken.
131 if (s)
36 131 XML_ParserFree(s);
37 131 }
38
39
40 template <typename Handler>
41 struct ExpatWrapper<Handler>::CallbackWrapper
42 {
43 // TODO(ighvh): use template<auto> when C++17 is mandatory (so in about 10
44 // years)
45 template <typename T, T, int = 0>
46 struct Impl;
47
48 // We use a partial specialisation of the struct above
49 // to extract the argument types (Args) from the Member function.
50 template <
51 typename... Args,
52 void (Handler::*callback)(Args...),
53 int level_change>
54 struct Impl<void (Handler::*)(Args...), callback, level_change>
55 {
56 2998 static void XMLCALL call(void *userdata, Args... args)
57 {
58 2998 auto &This = *reinterpret_cast<ExpatWrapper<Handler> *>(userdata);
59 // increment (start handler only)
60 2998 This.level_ += level_change == 1;
61
3/4
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1432 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1565 times.
2998 if (This.pending_exception_)
62 1 return;
63 try {
64
3/4
✓ Branch 4 taken 1432 times.
✗ Branch 5 not taken.
✓ Branch 10 taken 1564 times.
✓ Branch 11 taken 1 times.
2997 (static_cast<Handler &>(This).*callback)(args...);
65 }
66 2 catch (...) {
67 1 This.pending_exception_ = std::current_exception();
68
1/4
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
1 XML_StopParser(This.parser_.get(), false);
69 }
70 // decrement (end handler only)
71 2997 This.level_ -= level_change == -1;
72 }
73 };
74 };
75
76 template <typename Handler>
77 132 inline ExpatWrapper<Handler>::ExpatWrapper(const char *encoding)
78 {
79
1/2
✓ Branch 2 taken 132 times.
✗ Branch 3 not taken.
132 reset(encoding);
80 132 }
81
82 template <typename Handler>
83 132 inline void ExpatWrapper<Handler>::reset(const char *encoding)
84 {
85 132 pending_exception_ = nullptr;
86 132 level_ = 0;
87 132 parser_.reset(XML_ParserCreate(encoding));
88
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 132 times.
132 if (!parser_)
89 throw PdCom::Exception("Could not create XML parser");
90
91 using W1 = typename CallbackWrapper::template Impl<
92 decltype(&Handler::startElement), &Handler::startElement, 1>;
93 using W2 = typename CallbackWrapper::template Impl<
94 decltype(&Handler::endElement), &Handler::endElement, -1>;
95
96 132 XML_SetUserData(parser_.get(), this);
97 132 XML_SetStartElementHandler(parser_.get(), &W1::call);
98 132 XML_SetEndElementHandler(parser_.get(), &W2::call);
99 132 }
100
101 template <typename Handler>
102 inline bool
103 858 ExpatWrapper<Handler>::parse(const char *s, std::size_t n, bool final)
104 {
105
2/2
✓ Branch 3 taken 857 times.
✓ Branch 4 taken 1 times.
858 if (XML_STATUS_OK == XML_Parse(parser_.get(), s, n, final))
106 857 return true;
107
108 1 const XML_Error err_code = XML_GetErrorCode(parser_.get());
109
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 if (err_code == XML_ERROR_ABORTED && pending_exception_) {
110 2 auto pe = pending_exception_;
111 1 pending_exception_ = nullptr;
112 2 std::rethrow_exception(pe);
113 }
114
115 static_cast<Handler *>(this)->xmlError(XML_ErrorString(err_code));
116 return false;
117 }
118
119 }}} // namespace PdCom::impl::MsrProto
120
121 #endif // MSRPROTO_EXPAT_WRAPPER_H
122