| Directory: | ./ |
|---|---|
| File: | pdserv/src/msrproto/XmlParser.cpp |
| Date: | 2025-10-19 04:09:59 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 155 | 195 | 79.5% |
| Branches: | 127 | 229 | 55.5% |
| 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 "XmlParser.h" | ||
| 23 | #include "Session.h" | ||
| 24 | #include "../Debug.h" | ||
| 25 | |||
| 26 | #include <algorithm> | ||
| 27 | #include <cstring> | ||
| 28 | #include <sstream> | ||
| 29 | |||
| 30 | #undef log_debug | ||
| 31 | #define log_debug(...) | ||
| 32 | |||
| 33 | using namespace MsrProto; | ||
| 34 | |||
| 35 | ///////////////////////////////////////////////////////////////////////////// | ||
| 36 | 144 | XmlParser::XmlParser(size_t bufMax): bufLenMax(bufMax) | |
| 37 | { | ||
| 38 | 144 | parseState = FindElementStart; | |
| 39 | 144 | buf = 0; | |
| 40 | 144 | bufEnd = 0; | |
| 41 | 144 | inputEnd = 0; | |
| 42 | 144 | parsePos = 0; | |
| 43 | 144 | name = 0; | |
| 44 | 144 | } | |
| 45 | |||
| 46 | ///////////////////////////////////////////////////////////////////////////// | ||
| 47 | 288 | XmlParser::~XmlParser() | |
| 48 | { | ||
| 49 |
1/2✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
|
144 | delete[] buf; |
| 50 | 144 | } | |
| 51 | |||
| 52 | ///////////////////////////////////////////////////////////////////////////// | ||
| 53 | 8973 | std::streamsize XmlParser::read(std::streambuf* sb) | |
| 54 | { | ||
| 55 |
2/2✓ Branch 2 taken 144 times.
✓ Branch 3 taken 8829 times.
|
8973 | if (bufEnd == inputEnd) { |
| 56 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 144 times.
|
144 | if (name > buf + 1) { |
| 57 | // Name is not the second character in the buffer. | ||
| 58 | log_debug("shift up data"); | ||
| 59 | |||
| 60 | ✗ | moveData(buf); | |
| 61 | } | ||
| 62 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 144 times.
|
144 | else if (bufEnd >= buf + bufLenMax) { |
| 63 | ✗ | inputEnd = 0; | |
| 64 | ✗ | return 0; | |
| 65 | } | ||
| 66 | else { | ||
| 67 | log_debug("allocate new buffer"); | ||
| 68 | 144 | size_t bufLen = (bufEnd - buf) + bufIncrement; | |
| 69 | 144 | char *newBuf = new char[bufLen]; | |
| 70 | |||
| 71 | 144 | moveData(newBuf); | |
| 72 | |||
| 73 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
|
144 | delete[] buf; |
| 74 | 144 | buf = newBuf; | |
| 75 | 144 | bufEnd = buf + bufLen; | |
| 76 | } | ||
| 77 | } | ||
| 78 |
5/6✗ Branch 1 not taken.
✓ Branch 2 taken 8829 times.
✓ Branch 3 taken 824 times.
✓ Branch 4 taken 8005 times.
✓ Branch 7 taken 520 times.
✓ Branch 8 taken 304 times.
|
8829 | else if (parseState == FindElementStart and parsePos == inputEnd) { |
| 79 | 520 | inputEnd = buf; | |
| 80 | 520 | parsePos = buf; | |
| 81 | } | ||
| 82 | |||
| 83 | 8973 | std::streamsize n = sb->sgetn(inputEnd, bufEnd - inputEnd); | |
| 84 |
2/2✓ Branch 0 taken 8868 times.
✓ Branch 1 taken 105 times.
|
8973 | if (n > 0) |
| 85 | 8868 | inputEnd += n; | |
| 86 | |||
| 87 | 8973 | return n; | |
| 88 | } | ||
| 89 | |||
| 90 | ///////////////////////////////////////////////////////////////////////////// | ||
| 91 | 144 | void XmlParser::moveData(char* dst) | |
| 92 | { | ||
| 93 | // Move data to new location | ||
| 94 | 144 | std::copy(name, const_cast<const char*>(inputEnd), dst); | |
| 95 | |||
| 96 | // Update pointers | ||
| 97 | 144 | const ssize_t diff = dst - name; | |
| 98 | 144 | parsePos += diff; | |
| 99 | 144 | inputEnd += diff; | |
| 100 | 144 | name += diff; | |
| 101 | 144 | argument += diff; | |
| 102 | |||
| 103 | 144 | for (AttributeList::iterator it = attribute.begin(); | |
| 104 |
1/2✗ Branch 6 not taken.
✓ Branch 7 taken 144 times.
|
144 | it != attribute.end(); ++it) { |
| 105 | ✗ | it->first += diff; | |
| 106 | ✗ | it->second += diff; | |
| 107 | } | ||
| 108 | 144 | } | |
| 109 | |||
| 110 | ///////////////////////////////////////////////////////////////////////////// | ||
| 111 | ✗ | bool XmlParser::invalid() const | |
| 112 | { | ||
| 113 | ✗ | return !inputEnd; | |
| 114 | } | ||
| 115 | |||
| 116 | ///////////////////////////////////////////////////////////////////////////// | ||
| 117 | 11681 | XmlParser::operator bool() | |
| 118 | { | ||
| 119 |
1/2✓ Branch 2 taken 11681 times.
✗ Branch 3 not taken.
|
13890 | while (parsePos < inputEnd) { |
| 120 | // log_debug("parsepos=%zi state=%i \"%s\"", | ||
| 121 | // parsePos - buf, parseState, | ||
| 122 | // std::string(name, inputEnd - name).c_str() | ||
| 123 | // ); | ||
| 124 |
5/9✗ Branch 1 not taken.
✓ Branch 2 taken 11681 times.
✓ Branch 3 taken 1474 times.
✓ Branch 4 taken 2926 times.
✓ Branch 5 taken 2324 times.
✓ Branch 6 taken 4957 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
11681 | switch (parseState) { |
| 125 | 1474 | case FindElementStart: | |
| 126 | // At the end of this state, name set up correctly | ||
| 127 | // and there is at least one valid character following name | ||
| 128 | |||
| 129 |
1/2✓ Branch 4 taken 1474 times.
✗ Branch 5 not taken.
|
1474 | parsePos = std::find(parsePos, inputEnd, '<'); |
| 130 | |||
| 131 |
2/2✓ Branch 2 taken 861 times.
✓ Branch 3 taken 613 times.
|
1474 | if (parsePos + 2 >= inputEnd) { |
| 132 | // Smallest element needs at least 2 more characters, | ||
| 133 | // one for name and at least one for closing '>' | ||
| 134 | 861 | return false; | |
| 135 | } | ||
| 136 | |||
| 137 | 613 | name = ++parsePos; | |
| 138 | |||
| 139 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 613 times.
|
613 | if (!isalpha(*name)) { |
| 140 | // Name must start with an alpha character | ||
| 141 | ✗ | break; | |
| 142 | } | ||
| 143 | |||
| 144 | 613 | attribute.clear(); | |
| 145 | |||
| 146 | 613 | parseState = FindElementEnd; | |
| 147 | |||
| 148 | /* FALLTHRU */ | ||
| 149 | |||
| 150 | 3539 | case FindElementEnd: | |
| 151 | // Clobber white space | ||
| 152 |
2/2✓ Branch 2 taken 1605 times.
✓ Branch 3 taken 2822 times.
|
5315 | while (*parsePos == ' ') { |
| 153 | 1605 | *parsePos++ = '\0'; | |
| 154 |
2/2✓ Branch 2 taken 717 times.
✓ Branch 3 taken 888 times.
|
1605 | if (parsePos == inputEnd) |
| 155 | 717 | return false; | |
| 156 | } | ||
| 157 | |||
| 158 | // Element that ends in /> | ||
| 159 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 2822 times.
|
2822 | if (*parsePos == '/') { |
| 160 | ✗ | if (parsePos + 1 >= inputEnd) | |
| 161 | ✗ | return false; | |
| 162 | ✗ | *parsePos++ = '\0'; | |
| 163 | |||
| 164 | ✗ | parseState = FindElementStart; | |
| 165 | |||
| 166 | ✗ | if (*parsePos++ == '>') { | |
| 167 | ✗ | return true; | |
| 168 | } | ||
| 169 | ✗ | break; | |
| 170 | } | ||
| 171 | |||
| 172 | // Element that ends in > | ||
| 173 |
2/2✓ Branch 2 taken 604 times.
✓ Branch 3 taken 2218 times.
|
2822 | if (!isalpha(*parsePos)) { |
| 174 | 604 | parseState = FindElementStart; | |
| 175 |
1/2✓ Branch 2 taken 604 times.
✗ Branch 3 not taken.
|
604 | if (*parsePos == '>') { |
| 176 | 604 | *parsePos++ = '\0'; | |
| 177 | |||
| 178 | 604 | return true; | |
| 179 | } | ||
| 180 | ✗ | break; | |
| 181 | } | ||
| 182 | |||
| 183 | 2218 | argument = parsePos; | |
| 184 | |||
| 185 | 2218 | parseState = FindArgumentName; | |
| 186 | |||
| 187 | /* FALLTHRU */ | ||
| 188 | |||
| 189 | 4542 | case FindArgumentName: | |
| 190 | // In this state, the argument name is searched for. It is | ||
| 191 | // terminated by a '=', ' ', '/' or '>' | ||
| 192 |
2/2✓ Branch 2 taken 12685 times.
✓ Branch 3 taken 3488 times.
|
27804 | while (!strchr("= />", *parsePos)) |
| 193 |
2/2✓ Branch 4 taken 1054 times.
✓ Branch 5 taken 11631 times.
|
12685 | if (++parsePos == inputEnd) |
| 194 | 1054 | return false; | |
| 195 | |||
| 196 |
2/2✓ Branch 2 taken 613 times.
✓ Branch 3 taken 2875 times.
|
3488 | if (*parsePos != '=') { |
| 197 | // Found an attribute without a value. Consider it to | ||
| 198 | // be a boolean which evaluates to true | ||
| 199 |
1/2✓ Branch 4 taken 613 times.
✗ Branch 5 not taken.
|
1226 | attribute.push_back( |
| 200 |
1/2✓ Branch 4 taken 613 times.
✗ Branch 5 not taken.
|
1226 | std::make_pair(argument, (const char*)0)); |
| 201 | |||
| 202 | 613 | parseState = FindElementEnd; | |
| 203 | 613 | break; | |
| 204 | } | ||
| 205 | |||
| 206 | // parsePos points to the '=' | ||
| 207 | |||
| 208 | // Need at least one following character to continue | ||
| 209 |
2/2✓ Branch 2 taken 271 times.
✓ Branch 3 taken 2604 times.
|
2875 | if (parsePos + 1 >= inputEnd) |
| 210 | 271 | return false; | |
| 211 | |||
| 212 | 2604 | quote = parsePos[1]; | |
| 213 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 2604 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
2604 | if (quote != '"' and quote != '\'') { |
| 214 | // Argument value is not surrounded with quotes | ||
| 215 | ✗ | *parsePos++ = '\0'; | |
| 216 | ✗ | attribute.push_back(std::make_pair(argument, parsePos++)); | |
| 217 | ✗ | parseState = FindArgumentValue; | |
| 218 | ✗ | break; | |
| 219 | } | ||
| 220 |
2/2✓ Branch 2 taken 999 times.
✓ Branch 3 taken 1605 times.
|
2604 | else if (parsePos + 2 >= inputEnd) |
| 221 | // Quoted argument value. Need at least 2 following chars | ||
| 222 | // to continue | ||
| 223 | 999 | return false; | |
| 224 | |||
| 225 | 1605 | *parsePos = '\0'; // Clobber '=' | |
| 226 |
2/4✓ Branch 8 taken 1605 times.
✗ Branch 9 not taken.
✓ Branch 14 taken 1605 times.
✗ Branch 15 not taken.
|
1605 | attribute.push_back(std::make_pair(argument, parsePos + 2)); |
| 227 | 1605 | parsePos += 2; | |
| 228 | 1605 | parseState = FindQuotedArgumentValue; | |
| 229 | |||
| 230 | /* FALLTHRU */ | ||
| 231 | |||
| 232 | 6562 | case FindQuotedArgumentValue: | |
| 233 | 6562 | parsePos = std::find(parsePos, inputEnd, quote); | |
| 234 |
2/2✓ Branch 2 taken 4966 times.
✓ Branch 3 taken 1596 times.
|
6562 | if (parsePos + 1 >= inputEnd) |
| 235 | 4966 | return false; | |
| 236 | |||
| 237 | 1596 | *parsePos++ = '\0'; | |
| 238 | 1596 | parseState = FindElementEnd; | |
| 239 | |||
| 240 | /* FALLTHRU */ | ||
| 241 | |||
| 242 | 1596 | case FindArgumentValue: | |
| 243 |
3/4✓ Branch 2 taken 566 times.
✓ Branch 3 taken 1030 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 566 times.
|
1596 | while (*parsePos != ' ' and *parsePos != '>') { |
| 244 | ✗ | if (++parsePos == inputEnd) | |
| 245 | ✗ | return false; | |
| 246 | } | ||
| 247 | |||
| 248 | 1596 | parseState = FindElementEnd; | |
| 249 | 1596 | break; | |
| 250 | |||
| 251 | ✗ | case FindNameEnd: | |
| 252 | // At the end of this state, name is terminated with a | ||
| 253 | // closing \0 | ||
| 254 | |||
| 255 | // Name is any set of characters not in " />" | ||
| 256 | ✗ | while (!strchr(" />", *parsePos)) { | |
| 257 | ✗ | if (++parsePos == inputEnd) | |
| 258 | ✗ | return false; | |
| 259 | } | ||
| 260 | |||
| 261 | ✗ | parseState = FindElementEnd; | |
| 262 | |||
| 263 | ✗ | break; | |
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | ✗ | return false; | |
| 268 | } | ||
| 269 | |||
| 270 | ///////////////////////////////////////////////////////////////////////////// | ||
| 271 | 604 | const char *XmlParser::tag() const | |
| 272 | { | ||
| 273 | 604 | return name; | |
| 274 | } | ||
| 275 | |||
| 276 | ///////////////////////////////////////////////////////////////////////////// | ||
| 277 | 3017 | bool XmlParser::find(const char *name, const char **value) const | |
| 278 | { | ||
| 279 |
4/4✓ Branch 4 taken 1376 times.
✓ Branch 5 taken 1641 times.
✓ Branch 7 taken 1376 times.
✓ Branch 8 taken 1641 times.
|
11590 | for (AttributeList::const_iterator it = attribute.begin(); |
| 280 |
2/2✓ Branch 6 taken 10214 times.
✓ Branch 7 taken 1376 times.
|
11590 | it != attribute.end(); ++it) { |
| 281 |
4/6✗ Branch 2 not taken.
✓ Branch 3 taken 10214 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10214 times.
✓ Branch 6 taken 1641 times.
✓ Branch 7 taken 8573 times.
|
10214 | if (!strcasecmp(name, it->first)) { |
| 282 |
2/2✓ Branch 0 taken 1502 times.
✓ Branch 1 taken 139 times.
|
1641 | if (value) |
| 283 | 1502 | *value = it->second; | |
| 284 | 1641 | return true; | |
| 285 | } | ||
| 286 | } | ||
| 287 | |||
| 288 | 1376 | return false; | |
| 289 | } | ||
| 290 | |||
| 291 | ///////////////////////////////////////////////////////////////////////////// | ||
| 292 | 183 | bool XmlParser::isEqual(const char *name, const char *s) const | |
| 293 | { | ||
| 294 | 183 | const char *value; | |
| 295 | |||
| 296 |
3/6✓ Branch 2 taken 183 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 183 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 183 times.
✗ Branch 7 not taken.
|
183 | if (find(name, &value) and value) |
| 297 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 183 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 183 times.
|
183 | return !strcasecmp(value, s); |
| 298 | |||
| 299 | ✗ | return false; | |
| 300 | } | ||
| 301 | |||
| 302 | ///////////////////////////////////////////////////////////////////////////// | ||
| 303 | 688 | bool XmlParser::isTrue(const char *name) const | |
| 304 | { | ||
| 305 | 688 | bool val; | |
| 306 |
4/6✓ Branch 2 taken 114 times.
✓ Branch 3 taken 574 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 114 times.
✓ Branch 6 taken 114 times.
✗ Branch 7 not taken.
|
688 | return getBool(name, &val) and val; |
| 307 | } | ||
| 308 | |||
| 309 | ///////////////////////////////////////////////////////////////////////////// | ||
| 310 | 837 | bool XmlParser::getBool(const char *name, bool* val) const | |
| 311 | { | ||
| 312 | 837 | const char *str; | |
| 313 | |||
| 314 |
2/2✓ Branch 2 taken 713 times.
✓ Branch 3 taken 124 times.
|
837 | if (!(find(name, &str))) |
| 315 | 713 | return false; | |
| 316 | |||
| 317 | // Binary attribute, e.g <xsad sync> | ||
| 318 |
1/4✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
124 | *val = !(str |
| 319 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 124 times.
|
248 | and strcasecmp(str, "1") // Binary attr., e.g <xsad sync="1"> |
| 320 | ✗ | and strcasecmp(str, "true") // Binary attr., e.g sync="true"> | |
| 321 | ✗ | and strcasecmp(str, "on")); // Binary attr., e.g <xsad sync="on"> | |
| 322 | |||
| 323 | 124 | return true; | |
| 324 | } | ||
| 325 | |||
| 326 | ///////////////////////////////////////////////////////////////////////////// | ||
| 327 | 1279 | bool XmlParser::getString(const char *name, std::string &s) const | |
| 328 | { | ||
| 329 | 1279 | const char *value; | |
| 330 | |||
| 331 | 1279 | s.clear(); | |
| 332 | |||
| 333 |
5/6✓ Branch 2 taken 793 times.
✓ Branch 3 taken 486 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 793 times.
✓ Branch 6 taken 486 times.
✓ Branch 7 taken 793 times.
|
1279 | if (!(find(name, &value) and value)) |
| 334 | 486 | return false; | |
| 335 | |||
| 336 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 793 times.
|
793 | const char *pptr, *eptr = value + strlen(value); |
| 337 |
3/4✓ Branch 2 taken 847 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 54 times.
✓ Branch 6 taken 793 times.
|
901 | while ((pptr = std::find(value, eptr, '&')) != eptr) { |
| 338 | // FIXME: maybe also check for escape char, e.g. \" ?? | ||
| 339 | // this is difficult, because the quote character is not available | ||
| 340 | // here any more :( | ||
| 341 | |||
| 342 |
1/2✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
|
54 | s.append(value, pptr - value); |
| 343 | 54 | size_t len = eptr - pptr; | |
| 344 |
3/6✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
|
54 | if (len >= 4 and !strncmp(pptr, ">", 4)) { |
| 345 | ✗ | s.append(1, '>'); | |
| 346 | ✗ | value = pptr + 4; | |
| 347 | } | ||
| 348 |
4/6✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 36 times.
|
54 | else if (len >= 4 and !strncmp(pptr, "<", 4)) { |
| 349 |
1/2✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | s.append(1, '<'); |
| 350 | 18 | value = pptr + 4; | |
| 351 | } | ||
| 352 |
4/6✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 18 times.
|
36 | else if (len >= 5 and !strncmp(pptr, "&", 5)) { |
| 353 |
1/2✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | s.append(1, '&'); |
| 354 | 18 | value = pptr + 5; | |
| 355 | } | ||
| 356 |
3/6✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
18 | else if (len >= 6 and !strncmp(pptr, """, 6)) { |
| 357 |
1/2✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | s.append(1, '"'); |
| 358 | 18 | value = pptr + 6; | |
| 359 | } | ||
| 360 | ✗ | else if (len >= 6 and !strncmp(pptr, "'", 6)) { | |
| 361 | ✗ | s.append(1, '\''); | |
| 362 | ✗ | value = pptr + 6; | |
| 363 | } | ||
| 364 | else { | ||
| 365 | ✗ | s.append(1, '&'); | |
| 366 | ✗ | value = pptr + 1; | |
| 367 | } | ||
| 368 | } | ||
| 369 | |||
| 370 |
1/2✓ Branch 2 taken 793 times.
✗ Branch 3 not taken.
|
793 | s.append(value, eptr - value); |
| 371 | 793 | return true; | |
| 372 | } | ||
| 373 | |||
| 374 | ///////////////////////////////////////////////////////////////////////////// | ||
| 375 | 354 | bool XmlParser::getUnsigned(const char *name, unsigned int &i) const | |
| 376 | { | ||
| 377 | 354 | const char *value; | |
| 378 | |||
| 379 |
5/6✓ Branch 2 taken 246 times.
✓ Branch 3 taken 108 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 246 times.
✓ Branch 6 taken 108 times.
✓ Branch 7 taken 246 times.
|
354 | if (!(find(name, &value)) or !value) |
| 380 | 108 | return false; | |
| 381 | |||
| 382 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 246 times.
|
246 | i = strtoul(value, 0, 0); |
| 383 | 246 | return true; | |
| 384 | } | ||
| 385 | |||
| 386 | ///////////////////////////////////////////////////////////////////////////// | ||
| 387 | 44 | bool XmlParser::getUnsignedList(const char *name, | |
| 388 | std::list<unsigned int> &intList) const | ||
| 389 | { | ||
| 390 | 44 | const char *value; | |
| 391 | |||
| 392 |
3/6✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 44 times.
|
44 | if (!(find(name, &value)) or !value) |
| 393 | ✗ | return false; | |
| 394 | |||
| 395 |
2/4✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 44 times.
✗ Branch 10 not taken.
|
88 | std::istringstream is(value); |
| 396 |
2/4✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
|
44 | is.imbue(std::locale::classic()); |
| 397 | |||
| 398 |
3/4✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 44 times.
|
88 | while (is) { |
| 399 | 44 | unsigned int i; | |
| 400 | 44 | char comma; | |
| 401 | |||
| 402 |
1/2✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
|
44 | is >> i; |
| 403 |
2/4✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
|
44 | if (is) |
| 404 |
1/2✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
|
44 | intList.push_back(i); |
| 405 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | is >> comma; |
| 406 | } | ||
| 407 | |||
| 408 | 44 | return true; | |
| 409 | } | ||
| 410 |