GCC Code Coverage Report


Directory: ./
File: pdserv/src/msrproto/XmlElement.cpp
Date: 2024-12-15 04:08:34
Exec Total Coverage
Lines: 100 101 99.0%
Branches: 49 71 69.0%

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 2406 XmlElement::XmlElement(const char *name, std::ostream &os,
39 2406 size_t level, std::string *id):
40 2406 level(level), id(id), os(os), name(name)
41 {
42
4/8
✓ Branch 6 taken 2406 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 2406 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2406 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2406 times.
✗ Branch 17 not taken.
2406 this->os << std::string(level,' ') << '<' << name;
43 2406 printed = false;
44 2406 }
45
46 /////////////////////////////////////////////////////////////////////////////
47 4812 XmlElement::~XmlElement()
48 {
49
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2406 times.
✓ Branch 3 taken 385 times.
✓ Branch 4 taken 2021 times.
2406 if (printed)
50 385 os << std::string(level, ' ') << "</" << name;
51 else {
52
6/6
✓ Branch 1 taken 967 times.
✓ Branch 2 taken 1054 times.
✓ Branch 7 taken 108 times.
✓ Branch 8 taken 859 times.
✓ Branch 9 taken 108 times.
✓ Branch 10 taken 1913 times.
2021 if (id and !id->empty())
53 108 Attribute(*this,"id").setEscaped(*id);
54 2021 os << '/';
55 }
56
57 2406 os << ">\r\n";
58 2406 }
59
60 /////////////////////////////////////////////////////////////////////////////
61 1054 XmlElement XmlElement::createChild(const char* name)
62 {
63
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1054 times.
✓ Branch 3 taken 385 times.
✓ Branch 4 taken 669 times.
1054 if (!printed) {
64
5/6
✓ Branch 1 taken 385 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 380 times.
✓ Branch 9 taken 5 times.
✓ Branch 10 taken 380 times.
385 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 385 os << ">\r\n";
68 }
69
70 1054 printed = 1;
71
72 1054 return XmlElement(name, os, level+1, 0);
73 }
74
75 /////////////////////////////////////////////////////////////////////////////
76 // XmlElement::Attribute
77 /////////////////////////////////////////////////////////////////////////////
78 7316 XmlElement::Attribute::Attribute(XmlElement& el, const char *name):
79 7316 os(el.os)
80 {
81 7316 os << ' ' << name << "=\"";
82 7316 }
83
84 /////////////////////////////////////////////////////////////////////////////
85 14632 XmlElement::Attribute::~Attribute()
86 {
87 7316 os << '"';
88 7316 }
89
90 /////////////////////////////////////////////////////////////////////////////
91 939 std::ostream& XmlElement::Attribute::operator<<(const char *s)
92 {
93 939 os << s;
94 939 return os;
95 }
96
97 /////////////////////////////////////////////////////////////////////////////
98 1044 std::ostream& XmlElement::Attribute::operator <<( struct timespec const& ts)
99 {
100
1/2
✓ Branch 2 taken 1044 times.
✗ Branch 3 not taken.
2088 std::ostringstream time;
101
1/2
✓ Branch 3 taken 1044 times.
✗ Branch 4 not taken.
1044 time << ts.tv_sec << '.'
102
4/8
✓ Branch 2 taken 1044 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1044 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1044 times.
✗ Branch 11 not taken.
✓ Branch 17 taken 1044 times.
✗ Branch 18 not taken.
1044 << std::setfill('0') << std::setw(6) << ts.tv_nsec / 1000;
103
104
2/4
✓ Branch 4 taken 1044 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1044 times.
✗ Branch 9 not taken.
1044 os << time.str();
105 2088 return os;
106 }
107
108 /////////////////////////////////////////////////////////////////////////////
109 945 void XmlElement::Attribute::setEscaped( const std::string& str)
110 {
111 945 const char *escape = "<>&\"'";
112 945 size_t start = 0, pos;
113
114
2/2
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 945 times.
1125 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 945 times.
✗ Branch 7 not taken.
945 os << str.substr(start);
142 945 }
143
144 /////////////////////////////////////////////////////////////////////////////
145 164 void XmlElement::Attribute::csv(const Variable* var, const char *buf,
146 size_t nblocks, std::streamsize precision)
147 {
148 164 char delim = '\0';
149
150 // Save current and set new precision
151 164 precision = os.precision(precision);
152
153
2/2
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 164 times.
492 while (nblocks--) {
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164 times.
164 if (delim)
155 os << delim;
156 164 delim = ',';
157 164 var->dtype.print(os, buf, buf, buf+var->memSize);
158 164 buf += var->memSize;
159 }
160
161 // Reset previous precision
162 164 os.precision(precision);
163 164 }
164
165 /////////////////////////////////////////////////////////////////////////////
166 846 void XmlElement::Attribute::base64( const void *data, size_t len) const
167 {
168 static const char *base64Chr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
169 "abcdefghijklmnopqrstuvwxyz0123456789+/";
170 846 size_t i = 0;
171 846 size_t rem = len % 3;
172 846 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 4964 times.
✓ Branch 1 taken 846 times.
10774 while (i != len - rem) {
176 9928 os << base64Chr[ buf[i ] >> 2]
177 4964 << base64Chr[((buf[i ] & 0x03) << 4) + (buf[i+1] >> 4)]
178 4964 << base64Chr[((buf[i+1] & 0x0f) << 2) + (buf[i+2] >> 6)]
179 19856 << base64Chr[ (buf[i+2] & 0x3f) ];
180
181 4964 i += 3;
182 }
183
184 // Convert the remaining 1 or 2 characters
185
2/3
✓ Branch 0 taken 362 times.
✓ Branch 1 taken 484 times.
✗ Branch 2 not taken.
846 switch (rem) {
186 362 case 2:
187 724 os << base64Chr[ buf[i ] >> 2]
188 362 << base64Chr[((buf[i ] & 0x03) << 4) + (buf[i+1] >> 4)]
189 362 << base64Chr[ (buf[i+1] & 0x0f) << 2]
190 1448 << '=';
191 362 break;
192 484 case 1:
193 968 os << base64Chr[ buf[i] >> 2]
194 484 << base64Chr[ (buf[i] & 0x03) << 4]
195 1452 << "==";
196 484 break;
197 }
198 846 }
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