| 354 | |
| 355 | |
| 356 | const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) |
| 357 | { |
| 358 | // Presume an entity, and pull it out. |
| 359 | *length = 0; |
| 360 | |
| 361 | if ( *(p+1) == '#' && *(p+2) ) { |
| 362 | unsigned long ucs = 0; |
| 363 | TIXMLASSERT( sizeof( ucs ) >= 4 ); |
| 364 | ptrdiff_t delta = 0; |
| 365 | unsigned mult = 1; |
| 366 | static const char SEMICOLON = ';'; |
| 367 | |
| 368 | if ( *(p+2) == 'x' ) { |
| 369 | // Hexadecimal. |
| 370 | const char* q = p+3; |
| 371 | if ( !(*q) ) { |
| 372 | return 0; |
| 373 | } |
| 374 | |
| 375 | q = strchr( q, SEMICOLON ); |
| 376 | |
| 377 | if ( !q ) { |
| 378 | return 0; |
| 379 | } |
| 380 | TIXMLASSERT( *q == SEMICOLON ); |
| 381 | |
| 382 | delta = q-p; |
| 383 | --q; |
| 384 | |
| 385 | while ( *q != 'x' ) { |
| 386 | unsigned int digit = 0; |
| 387 | |
| 388 | if ( *q >= '0' && *q <= '9' ) { |
| 389 | digit = *q - '0'; |
| 390 | } |
| 391 | else if ( *q >= 'a' && *q <= 'f' ) { |
| 392 | digit = *q - 'a' + 10; |
| 393 | } |
| 394 | else if ( *q >= 'A' && *q <= 'F' ) { |
| 395 | digit = *q - 'A' + 10; |
| 396 | } |
| 397 | else { |
| 398 | return 0; |
| 399 | } |
| 400 | TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); |
| 401 | TIXMLASSERT( digit >= 0 && digit < 16); |
| 402 | const unsigned int digitScaled = mult * digit; |
| 403 | TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); |
| 404 | ucs += digitScaled; |
| 405 | TIXMLASSERT( mult <= UINT_MAX / 16 ); |
| 406 | mult *= 16; |
| 407 | --q; |
| 408 | } |
| 409 | } |
| 410 | else { |
| 411 | // Decimal. |
| 412 | const char* q = p+2; |
| 413 | if ( !(*q) ) { |
nothing calls this directly
no outgoing calls
no test coverage detected