GCC Code Coverage Report


Directory: ./
File: pdserv-1.1.0/src/msrproto/XmlElement.cpp
Date: 2026-09-27 04:07:30
Exec Total Coverage
Lines: 0 91 0.0%
Branches: 0 75 0.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 #include "Variable.h"
28 #include "Parameter.h"
29 #include "Channel.h"
30 //#include "FindFirstOf.h"
31
32 #include <iomanip>
33 #include <algorithm>
34 #include <cstring> // strpbrk()
35
36 using namespace MsrProto;
37
38 /////////////////////////////////////////////////////////////////////////////
39 // XmlElement
40 /////////////////////////////////////////////////////////////////////////////
41 ✗ XmlElement::XmlElement(const char *name, std::ostream &os,
42 ✗ size_t level, std::string *id):
43 ✗ level(level), id(id), os(os), name(name)
44 {
45 ✗ this->os << std::string(level,' ') << '<' << name;
46 ✗ printed = false;
47 }
48
49 /////////////////////////////////////////////////////////////////////////////
50 ✗ XmlElement::~XmlElement()
51 {
52 ✗ if (printed)
53 ✗ os << std::string(level, ' ') << "</" << name;
54 else {
55 ✗ if (id and !id->empty())
56 ✗ Attribute(*this,"id").setEscaped(id->c_str());
57 ✗ os << '/';
58 }
59
60 ✗ os << ">\r\n";
61 }
62
63 /////////////////////////////////////////////////////////////////////////////
64 ✗ XmlElement XmlElement::createChild(const char* name)
65 {
66 ✗ if (!printed) {
67 ✗ if (id and !id->empty())
68 ✗ Attribute(*this,"id").setEscaped(id->c_str());
69
70 ✗ os << ">\r\n";
71 }
72
73 ✗ printed = 1;
74
75 ✗ return XmlElement(name, os, level+1, 0);
76 }
77
78 /////////////////////////////////////////////////////////////////////////////
79 // XmlElement::Attribute
80 /////////////////////////////////////////////////////////////////////////////
81 ✗ XmlElement::Attribute::Attribute(XmlElement& el, const char *name):
82 ✗ os(el.os)
83 {
84 ✗ os << ' ' << name << "=\"";
85 }
86
87 /////////////////////////////////////////////////////////////////////////////
88 ✗ XmlElement::Attribute::~Attribute()
89 {
90 ✗ os << '"';
91 }
92
93 /////////////////////////////////////////////////////////////////////////////
94 ✗ std::ostream& XmlElement::Attribute::operator<<(const char *s)
95 {
96 ✗ os << s;
97 ✗ return os;
98 }
99
100 /////////////////////////////////////////////////////////////////////////////
101 ✗ std::ostream& XmlElement::Attribute::operator <<( struct timespec const& ts)
102 {
103 ✗ std::ostringstream time;
104 ✗ time << ts.tv_sec << '.'
105 ✗ << std::setfill('0') << std::setw(6) << ts.tv_nsec / 1000;
106
107 ✗ os << time.str();
108 ✗ return os;
109 }
110
111 /////////////////////////////////////////////////////////////////////////////
112 ✗ void XmlElement::Attribute::setEscaped( const char *v)
113 {
114 ✗ const char *escape = "<>&\"'";
115 const char *p;
116
117 ✗ while ((p = strpbrk(v, escape))) {
118 ✗ os << std::string(v, p);
119 ✗ switch (*p) {
120 ✗ case '<':
121 ✗ os << "&lt;";
122 ✗ break;
123
124 ✗ case '>':
125 ✗ os << "&gt;";
126 ✗ break;
127
128 ✗ case '&':
129 ✗ os << "&amp;";
130 ✗ break;
131
132 ✗ case '"':
133 ✗ os << "&quot;";
134 ✗ break;
135
136 ✗ case '\'':
137 ✗ os << "&apos;";
138 ✗ break;
139 }
140
141 ✗ v = p + 1;
142 }
143
144 ✗ os << v;
145 }
146
147 /////////////////////////////////////////////////////////////////////////////
148 ✗ void XmlElement::Attribute::csv(const Variable* var, const char *buf,
149 size_t nblocks, size_t precision)
150 {
151 ✗ char delim = '\0';
152
153 ✗ os.precision(precision);
154 ✗ while (nblocks--) {
155 ✗ if (delim)
156 ✗ os << delim;
157 ✗ delim = ',';
158 ✗ var->dtype.print(os, buf, buf, buf+var->memSize);
159 ✗ buf += var->memSize;
160 }
161 }
162
163 /////////////////////////////////////////////////////////////////////////////
164 ✗ void XmlElement::Attribute::base64( const void *data, size_t len) const
165 {
166 static const char *base64Chr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
167 "abcdefghijklmnopqrstuvwxyz0123456789+/";
168 ✗ size_t i = 0;
169 ✗ size_t rem = len % 3;
170 ✗ const unsigned char *buf = reinterpret_cast<const unsigned char*>(data);
171
172 // First convert all characters in chunks of 3
173 ✗ while (i != len - rem) {
174 ✗ os << base64Chr[ buf[i ] >> 2]
175 ✗ << base64Chr[((buf[i ] & 0x03) << 4) + (buf[i+1] >> 4)]
176 ✗ << base64Chr[((buf[i+1] & 0x0f) << 2) + (buf[i+2] >> 6)]
177 ✗ << base64Chr[ (buf[i+2] & 0x3f) ];
178
179 ✗ i += 3;
180 }
181
182 // Convert the remaining 1 or 2 characters
183 ✗ switch (rem) {
184 ✗ case 2:
185 ✗ os << base64Chr[ buf[i ] >> 2]
186 ✗ << base64Chr[((buf[i ] & 0x03) << 4) + (buf[i+1] >> 4)]
187 ✗ << base64Chr[ (buf[i+1] & 0x0f) << 2]
188 ✗ << '=';
189 ✗ break;
190 ✗ case 1:
191 ✗ os << base64Chr[ buf[i] >> 2]
192 ✗ << base64Chr[ (buf[i] & 0x03) << 4]
193 ✗ << "==";
194 ✗ break;
195 }
196 }
197
198 /////////////////////////////////////////////////////////////////////////////
199 ✗ void XmlElement::Attribute::hexDec( const void *data, size_t len) const
200 {
201 ✗ const unsigned char *buf =
202 reinterpret_cast<const unsigned char*>(data);
203 ✗ const char *hexValue[256] = {
204 "00", "01", "02", "03", "04", "05", "06", "07", "08", "09",
205 "0A", "0B", "0C", "0D", "0E", "0F", "10", "11", "12", "13",
206 "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D",
207 "1E", "1F", "20", "21", "22", "23", "24", "25", "26", "27",
208 "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", "30", "31",
209 "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B",
210 "3C", "3D", "3E", "3F", "40", "41", "42", "43", "44", "45",
211 "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
212 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
213 "5A", "5B", "5C", "5D", "5E", "5F", "60", "61", "62", "63",
214 "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D",
215 "6E", "6F", "70", "71", "72", "73", "74", "75", "76", "77",
216 "78", "79", "7A", "7B", "7C", "7D", "7E", "7F", "80", "81",
217 "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B",
218 "8C", "8D", "8E", "8F", "90", "91", "92", "93", "94", "95",
219 "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
220 "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9",
221 "AA", "AB", "AC", "AD", "AE", "AF", "B0", "B1", "B2", "B3",
222 "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD",
223 "BE", "BF", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7",
224 "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "D0", "D1",
225 "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB",
226 "DC", "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4", "E5",
227 "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
228 "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9",
229 "FA", "FB", "FC", "FD", "FE", "FF"};
230
231 ✗ while (len--)
232 ✗ os << hexValue[*buf++];
233 }
234