GCC Code Coverage Report


Directory: ./
File: pdserv-1.1.0/src/msrproto/XmlElement.cpp
Date: 2023-11-12 04:06:57
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