| Directory: | ./ |
|---|---|
| File: | pdserv/src/msrproto/XmlElement.cpp |
| Date: | 2025-11-09 04:09:32 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 100 | 101 | 99.0% |
| Branches: | 49 | 71 | 69.0% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /***************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2010 Richard Hacker (lerichi at gmx dot net) | ||
| 4 | * | ||
| 5 | * This file is part of the pdserv library. | ||
| 6 | * | ||
| 7 | * The pdserv library is free software: you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU Lesser General Public License as published | ||
| 9 | * by the Free Software Foundation, either version 3 of the License, or (at | ||
| 10 | * your option) any later version. | ||
| 11 | * | ||
| 12 | * The pdserv library is distributed in the hope that it will be useful, but | ||
| 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
| 14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | ||
| 15 | * License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public License | ||
| 18 | * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>. | ||
| 19 | * | ||
| 20 | ****************************************************************************/ | ||
| 21 | |||
| 22 | #include "XmlElement.h" | ||
| 23 | #include "Variable.h" | ||
| 24 | #include "../Debug.h" | ||
| 25 | |||
| 26 | #include <sstream> | ||
| 27 | #include <iomanip> | ||
| 28 | #include <algorithm> | ||
| 29 | #include <cstring> // strpbrk() | ||
| 30 | |||
| 31 | using namespace MsrProto; | ||
| 32 | |||
| 33 | ///////////////////////////////////////////////////////////////////////////// | ||
| 34 | // XmlElement | ||
| 35 | ///////////////////////////////////////////////////////////////////////////// | ||
| 36 | 2403 | XmlElement::XmlElement(const char *name, std::ostream &os, | |
| 37 | 2403 | size_t level, std::string *id): | |
| 38 | 2403 | level(level), id(id), os(os), name(name) | |
| 39 | { | ||
| 40 |
4/8✓ Branch 6 taken 2403 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 2403 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2403 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2403 times.
✗ Branch 17 not taken.
|
2403 | this->os << std::string(level,' ') << '<' << name; |
| 41 | 2403 | printed = false; | |
| 42 | 2403 | } | |
| 43 | |||
| 44 | ///////////////////////////////////////////////////////////////////////////// | ||
| 45 | 4806 | XmlElement::~XmlElement() | |
| 46 | { | ||
| 47 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 2403 times.
✓ Branch 3 taken 384 times.
✓ Branch 4 taken 2019 times.
|
2403 | if (printed) |
| 48 | 384 | os << std::string(level, ' ') << "</" << name; | |
| 49 | else { | ||
| 50 |
6/6✓ Branch 1 taken 967 times.
✓ Branch 2 taken 1052 times.
✓ Branch 7 taken 108 times.
✓ Branch 8 taken 859 times.
✓ Branch 9 taken 108 times.
✓ Branch 10 taken 1911 times.
|
2019 | if (id and !id->empty()) |
| 51 | 108 | Attribute(*this,"id").setEscaped(*id); | |
| 52 | 2019 | os << '/'; | |
| 53 | } | ||
| 54 | |||
| 55 | 2403 | os << ">\r\n"; | |
| 56 | 2403 | } | |
| 57 | |||
| 58 | ///////////////////////////////////////////////////////////////////////////// | ||
| 59 | 1052 | XmlElement XmlElement::createChild(const char* name) | |
| 60 | { | ||
| 61 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 1052 times.
✓ Branch 3 taken 384 times.
✓ Branch 4 taken 668 times.
|
1052 | if (!printed) { |
| 62 |
5/6✓ Branch 1 taken 384 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 379 times.
✓ Branch 9 taken 5 times.
✓ Branch 10 taken 379 times.
|
384 | if (id and !id->empty()) |
| 63 |
1/2✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
|
5 | Attribute(*this,"id").setEscaped(*id); |
| 64 | |||
| 65 | 384 | os << ">\r\n"; | |
| 66 | } | ||
| 67 | |||
| 68 | 1052 | printed = 1; | |
| 69 | |||
| 70 | 1052 | return XmlElement(name, os, level+1, 0); | |
| 71 | } | ||
| 72 | |||
| 73 | ///////////////////////////////////////////////////////////////////////////// | ||
| 74 | // XmlElement::Attribute | ||
| 75 | ///////////////////////////////////////////////////////////////////////////// | ||
| 76 | 7310 | XmlElement::Attribute::Attribute(XmlElement& el, const char *name): | |
| 77 | 7310 | os(el.os) | |
| 78 | { | ||
| 79 | 7310 | os << ' ' << name << "=\""; | |
| 80 | 7310 | } | |
| 81 | |||
| 82 | ///////////////////////////////////////////////////////////////////////////// | ||
| 83 | 14620 | XmlElement::Attribute::~Attribute() | |
| 84 | { | ||
| 85 | 7310 | os << '"'; | |
| 86 | 7310 | } | |
| 87 | |||
| 88 | ///////////////////////////////////////////////////////////////////////////// | ||
| 89 | 939 | std::ostream& XmlElement::Attribute::operator<<(const char *s) | |
| 90 | { | ||
| 91 | 939 | os << s; | |
| 92 | 939 | return os; | |
| 93 | } | ||
| 94 | |||
| 95 | ///////////////////////////////////////////////////////////////////////////// | ||
| 96 | 1043 | std::ostream& XmlElement::Attribute::operator <<( struct timespec const& ts) | |
| 97 | { | ||
| 98 |
1/2✓ Branch 2 taken 1043 times.
✗ Branch 3 not taken.
|
2086 | std::ostringstream time; |
| 99 |
1/2✓ Branch 3 taken 1043 times.
✗ Branch 4 not taken.
|
1043 | time << ts.tv_sec << '.' |
| 100 |
4/8✓ Branch 2 taken 1043 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1043 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1043 times.
✗ Branch 11 not taken.
✓ Branch 17 taken 1043 times.
✗ Branch 18 not taken.
|
1043 | << std::setfill('0') << std::setw(6) << ts.tv_nsec / 1000; |
| 101 | |||
| 102 |
2/4✓ Branch 4 taken 1043 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1043 times.
✗ Branch 9 not taken.
|
1043 | os << time.str(); |
| 103 | 2086 | return os; | |
| 104 | } | ||
| 105 | |||
| 106 | ///////////////////////////////////////////////////////////////////////////// | ||
| 107 | 945 | void XmlElement::Attribute::setEscaped( const std::string& str) | |
| 108 | { | ||
| 109 | 945 | const char *escape = "<>&\"'"; | |
| 110 | 945 | size_t start = 0, pos; | |
| 111 | |||
| 112 |
2/2✓ Branch 2 taken 90 times.
✓ Branch 3 taken 945 times.
|
1125 | while (std::string::npos != (pos = str.find_first_of(escape, start))) { |
| 113 |
1/2✓ Branch 6 taken 90 times.
✗ Branch 7 not taken.
|
90 | os << str.substr(start, pos - start); |
| 114 |
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]) { |
| 115 | 18 | case '<': | |
| 116 | 18 | os << "<"; | |
| 117 | 18 | break; | |
| 118 | |||
| 119 | 18 | case '>': | |
| 120 | 18 | os << ">"; | |
| 121 | 18 | break; | |
| 122 | |||
| 123 | 18 | case '&': | |
| 124 | 18 | os << "&"; | |
| 125 | 18 | break; | |
| 126 | |||
| 127 | 18 | case '"': | |
| 128 | 18 | os << """; | |
| 129 | 18 | break; | |
| 130 | |||
| 131 | 18 | case '\'': | |
| 132 | 18 | os << "'"; | |
| 133 | 18 | break; | |
| 134 | } | ||
| 135 | |||
| 136 | 90 | start = pos + 1; | |
| 137 | } | ||
| 138 | |||
| 139 |
1/2✓ Branch 6 taken 945 times.
✗ Branch 7 not taken.
|
945 | os << str.substr(start); |
| 140 | 945 | } | |
| 141 | |||
| 142 | ///////////////////////////////////////////////////////////////////////////// | ||
| 143 | 164 | void XmlElement::Attribute::csv(const Variable* var, const char *buf, | |
| 144 | size_t nblocks, std::streamsize precision) | ||
| 145 | { | ||
| 146 | 164 | char delim = '\0'; | |
| 147 | |||
| 148 | // Save current and set new precision | ||
| 149 | 164 | precision = os.precision(precision); | |
| 150 | |||
| 151 |
2/2✓ Branch 0 taken 164 times.
✓ Branch 1 taken 164 times.
|
492 | while (nblocks--) { |
| 152 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 164 times.
|
164 | if (delim) |
| 153 | ✗ | os << delim; | |
| 154 | 164 | delim = ','; | |
| 155 | 164 | var->dtype.print(os, buf, buf, buf+var->memSize); | |
| 156 | 164 | buf += var->memSize; | |
| 157 | } | ||
| 158 | |||
| 159 | // Reset previous precision | ||
| 160 | 164 | os.precision(precision); | |
| 161 | 164 | } | |
| 162 | |||
| 163 | ///////////////////////////////////////////////////////////////////////////// | ||
| 164 | 844 | void XmlElement::Attribute::base64( const void *data, size_t len) const | |
| 165 | { | ||
| 166 | static const char *base64Chr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
| 167 | "abcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
| 168 | 844 | size_t i = 0; | |
| 169 | 844 | size_t rem = len % 3; | |
| 170 | 844 | const unsigned char *buf = reinterpret_cast<const unsigned char*>(data); | |
| 171 | |||
| 172 | // First convert all characters in chunks of 3 | ||
| 173 |
2/2✓ Branch 0 taken 4954 times.
✓ Branch 1 taken 844 times.
|
10752 | while (i != len - rem) { |
| 174 | 9908 | os << base64Chr[ buf[i ] >> 2] | |
| 175 | 4954 | << base64Chr[((buf[i ] & 0x03) << 4) + (buf[i+1] >> 4)] | |
| 176 | 4954 | << base64Chr[((buf[i+1] & 0x0f) << 2) + (buf[i+2] >> 6)] | |
| 177 | 19816 | << base64Chr[ (buf[i+2] & 0x3f) ]; | |
| 178 | |||
| 179 | 4954 | i += 3; | |
| 180 | } | ||
| 181 | |||
| 182 | // Convert the remaining 1 or 2 characters | ||
| 183 |
2/3✓ Branch 0 taken 362 times.
✓ Branch 1 taken 482 times.
✗ Branch 2 not taken.
|
844 | switch (rem) { |
| 184 | 362 | case 2: | |
| 185 | 724 | os << base64Chr[ buf[i ] >> 2] | |
| 186 | 362 | << base64Chr[((buf[i ] & 0x03) << 4) + (buf[i+1] >> 4)] | |
| 187 | 362 | << base64Chr[ (buf[i+1] & 0x0f) << 2] | |
| 188 | 1448 | << '='; | |
| 189 | 362 | break; | |
| 190 | 482 | case 1: | |
| 191 | 964 | os << base64Chr[ buf[i] >> 2] | |
| 192 | 482 | << base64Chr[ (buf[i] & 0x03) << 4] | |
| 193 | 1446 | << "=="; | |
| 194 | 482 | break; | |
| 195 | } | ||
| 196 | 844 | } | |
| 197 | |||
| 198 | ///////////////////////////////////////////////////////////////////////////// | ||
| 199 | 52 | void XmlElement::Attribute::hexDec( const void *data, size_t len) const | |
| 200 | { | ||
| 201 | 52 | const unsigned char *buf = | |
| 202 | reinterpret_cast<const unsigned char*>(data); | ||
| 203 | 52 | 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 |
2/2✓ Branch 0 taken 732 times.
✓ Branch 1 taken 52 times.
|
1516 | while (len--) |
| 232 |
1/2✓ Branch 6 taken 732 times.
✗ Branch 7 not taken.
|
732 | os << hexValue[*buf++]; |
| 233 | 52 | } | |
| 234 |