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 << "<"; |
122 |
|
✗ |
break; |
123 |
|
|
|
124 |
|
✗ |
case '>': |
125 |
|
✗ |
os << ">"; |
126 |
|
✗ |
break; |
127 |
|
|
|
128 |
|
✗ |
case '&': |
129 |
|
✗ |
os << "&"; |
130 |
|
✗ |
break; |
131 |
|
|
|
132 |
|
✗ |
case '"': |
133 |
|
✗ |
os << """; |
134 |
|
✗ |
break; |
135 |
|
|
|
136 |
|
✗ |
case '\'': |
137 |
|
✗ |
os << "'"; |
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 |
|
|
|