GCC Code Coverage Report


Directory: ./
File: pdserv/src/msrproto/XmlElement.cpp
Date: 2023-11-12 04:06:57
Exec Total Coverage
Lines: 95 101 94.1%
Branches: 48 71 67.6%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright 2010 Richard Hacker (lerichi at gmx dot net)
6 *
7 * This file is part of the pdserv library.
8 *
9 * The pdserv library is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation, either version 3 of the License, or (at
12 * your option) any later version.
13 *
14 * The pdserv library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>.
21 *
22 *****************************************************************************/
23
24 #include "XmlElement.h"
25 #include "Variable.h"
26 #include "../Debug.h"
27
28 #include <sstream>
29 #include <iomanip>
30 #include <algorithm>
31 #include <cstring> // strpbrk()
32
33 using namespace MsrProto;
34
35 /////////////////////////////////////////////////////////////////////////////
36 // XmlElement
37 /////////////////////////////////////////////////////////////////////////////
38 1176 XmlElement::XmlElement(const char *name, std::ostream &os,
39 1176 size_t level, std::string *id):
40 1176 level(level), id(id), os(os), name(name)
41 {
42
4/8
✓ Branch 6 taken 1176 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1176 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1176 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1176 times.
✗ Branch 17 not taken.
1176 this->os << std::string(level,' ') << '<' << name;
43 1176 printed = false;
44 1176 }
45
46 /////////////////////////////////////////////////////////////////////////////
47 2352 XmlElement::~XmlElement()
48 {
49
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1176 times.
✓ Branch 3 taken 91 times.
✓ Branch 4 taken 1085 times.
1176 if (printed)
50 91 os << std::string(level, ' ') << "</" << name;
51 else {
52
6/6
✓ Branch 1 taken 789 times.
✓ Branch 2 taken 296 times.
✓ Branch 7 taken 76 times.
✓ Branch 8 taken 713 times.
✓ Branch 9 taken 76 times.
✓ Branch 10 taken 1009 times.
1085 if (id and !id->empty())
53 76 Attribute(*this,"id").setEscaped(*id);
54 1085 os << '/';
55 }
56
57 1176 os << ">\r\n";
58 1176 }
59
60 /////////////////////////////////////////////////////////////////////////////
61 296 XmlElement XmlElement::createChild(const char* name)
62 {
63
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 296 times.
✓ Branch 3 taken 91 times.
✓ Branch 4 taken 205 times.
296 if (!printed) {
64
5/6
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 86 times.
✓ Branch 9 taken 5 times.
✓ Branch 10 taken 86 times.
91 if (id and !id->empty())
65
1/2
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
5 Attribute(*this,"id").setEscaped(*id);
66
67 91 os << ">\r\n";
68 }
69
70 296 printed = 1;
71
72 296 return XmlElement(name, os, level+1, 0);
73 }
74
75 /////////////////////////////////////////////////////////////////////////////
76 // XmlElement::Attribute
77 /////////////////////////////////////////////////////////////////////////////
78 4418 XmlElement::Attribute::Attribute(XmlElement& el, const char *name):
79 4418 os(el.os)
80 {
81 4418 os << ' ' << name << "=\"";
82 4418 }
83
84 /////////////////////////////////////////////////////////////////////////////
85 8836 XmlElement::Attribute::~Attribute()
86 {
87 4418 os << '"';
88 4418 }
89
90 /////////////////////////////////////////////////////////////////////////////
91 789 std::ostream& XmlElement::Attribute::operator<<(const char *s)
92 {
93 789 os << s;
94 789 return os;
95 }
96
97 /////////////////////////////////////////////////////////////////////////////
98 614 std::ostream& XmlElement::Attribute::operator <<( struct timespec const& ts)
99 {
100
1/2
✓ Branch 2 taken 614 times.
✗ Branch 3 not taken.
1228 std::ostringstream time;
101
1/2
✓ Branch 3 taken 614 times.
✗ Branch 4 not taken.
614 time << ts.tv_sec << '.'
102
4/8
✓ Branch 2 taken 614 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 614 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 614 times.
✗ Branch 11 not taken.
✓ Branch 17 taken 614 times.
✗ Branch 18 not taken.
614 << std::setfill('0') << std::setw(6) << ts.tv_nsec / 1000;
103
104
2/4
✓ Branch 4 taken 614 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 614 times.
✗ Branch 9 not taken.
614 os << time.str();
105 1228 return os;
106 }
107
108 /////////////////////////////////////////////////////////////////////////////
109 767 void XmlElement::Attribute::setEscaped( const std::string& str)
110 {
111 767 const char *escape = "<>&\"'";
112 767 size_t start = 0, pos;
113
114
2/2
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 767 times.
947 while (std::string::npos != (pos = str.find_first_of(escape, start))) {
115
1/2
✓ Branch 6 taken 90 times.
✗ Branch 7 not taken.
90 os << str.substr(start, pos - start);
116
5/6
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
90 switch (str[pos]) {
117 18 case '<':
118 18 os << "&lt;";
119 18 break;
120
121 18 case '>':
122 18 os << "&gt;";
123 18 break;
124
125 18 case '&':
126 18 os << "&amp;";
127 18 break;
128
129 18 case '"':
130 18 os << "&quot;";
131 18 break;
132
133 18 case '\'':
134 18 os << "&apos;";
135 18 break;
136 }
137
138 90 start = pos + 1;
139 }
140
141
1/2
✓ Branch 6 taken 767 times.
✗ Branch 7 not taken.
767 os << str.substr(start);
142 767 }
143
144 /////////////////////////////////////////////////////////////////////////////
145 132 void XmlElement::Attribute::csv(const Variable* var, const char *buf,
146 size_t nblocks, std::streamsize precision)
147 {
148 132 char delim = '\0';
149
150 // Save current and set new precision
151 132 precision = os.precision(precision);
152
153
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 132 times.
396 while (nblocks--) {
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
132 if (delim)
155 os << delim;
156 132 delim = ',';
157 132 var->dtype.print(os, buf, buf, buf+var->memSize);
158 132 buf += var->memSize;
159 }
160
161 // Reset previous precision
162 132 os.precision(precision);
163 132 }
164
165 /////////////////////////////////////////////////////////////////////////////
166 98 void XmlElement::Attribute::base64( const void *data, size_t len) const
167 {
168 static const char *base64Chr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
169 "abcdefghijklmnopqrstuvwxyz0123456789+/";
170 98 size_t i = 0;
171 98 size_t rem = len % 3;
172 98 const unsigned char *buf = reinterpret_cast<const unsigned char*>(data);
173
174 // First convert all characters in chunks of 3
175
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 98 times.
546 while (i != len - rem) {
176 448 os << base64Chr[ buf[i ] >> 2]
177 224 << base64Chr[((buf[i ] & 0x03) << 4) + (buf[i+1] >> 4)]
178 224 << base64Chr[((buf[i+1] & 0x0f) << 2) + (buf[i+2] >> 6)]
179 896 << base64Chr[ (buf[i+2] & 0x3f) ];
180
181 224 i += 3;
182 }
183
184 // Convert the remaining 1 or 2 characters
185
1/3
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
98 switch (rem) {
186 98 case 2:
187 196 os << base64Chr[ buf[i ] >> 2]
188 98 << base64Chr[((buf[i ] & 0x03) << 4) + (buf[i+1] >> 4)]
189 98 << base64Chr[ (buf[i+1] & 0x0f) << 2]
190 392 << '=';
191 98 break;
192 case 1:
193 os << base64Chr[ buf[i] >> 2]
194 << base64Chr[ (buf[i] & 0x03) << 4]
195 << "==";
196 break;
197 }
198 98 }
199
200 /////////////////////////////////////////////////////////////////////////////
201 52 void XmlElement::Attribute::hexDec( const void *data, size_t len) const
202 {
203 52 const unsigned char *buf =
204 reinterpret_cast<const unsigned char*>(data);
205 52 const char *hexValue[256] = {
206 "00", "01", "02", "03", "04", "05", "06", "07", "08", "09",
207 "0A", "0B", "0C", "0D", "0E", "0F", "10", "11", "12", "13",
208 "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D",
209 "1E", "1F", "20", "21", "22", "23", "24", "25", "26", "27",
210 "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", "30", "31",
211 "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B",
212 "3C", "3D", "3E", "3F", "40", "41", "42", "43", "44", "45",
213 "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
214 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
215 "5A", "5B", "5C", "5D", "5E", "5F", "60", "61", "62", "63",
216 "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D",
217 "6E", "6F", "70", "71", "72", "73", "74", "75", "76", "77",
218 "78", "79", "7A", "7B", "7C", "7D", "7E", "7F", "80", "81",
219 "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B",
220 "8C", "8D", "8E", "8F", "90", "91", "92", "93", "94", "95",
221 "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
222 "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9",
223 "AA", "AB", "AC", "AD", "AE", "AF", "B0", "B1", "B2", "B3",
224 "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD",
225 "BE", "BF", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7",
226 "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "D0", "D1",
227 "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB",
228 "DC", "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4", "E5",
229 "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
230 "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9",
231 "FA", "FB", "FC", "FD", "FE", "FF"};
232
233
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 52 times.
1516 while (len--)
234
1/2
✓ Branch 6 taken 732 times.
✗ Branch 7 not taken.
732 os << hexValue[*buf++];
235 52 }
236