| 438 | } |
| 439 | |
| 440 | QByteArray parseValue(NodeKind kind, const QString& text, bool* ok) { |
| 441 | *ok = false; |
| 442 | QString s = text.trimmed(); |
| 443 | |
| 444 | // Allow empty for string types (will produce zero-length content, caller pads) |
| 445 | if (s.isEmpty()) { |
| 446 | if (kind == NodeKind::UTF8 || kind == NodeKind::UTF16) { |
| 447 | *ok = true; |
| 448 | return {}; |
| 449 | } |
| 450 | return {}; |
| 451 | } |
| 452 | |
| 453 | switch (kind) { |
| 454 | case NodeKind::Hex8: return parseHexBytes(stripHex(s), 1, ok); |
| 455 | case NodeKind::Hex16: { |
| 456 | QString cleaned = stripHex(s); |
| 457 | // Space-separated bytes → raw byte order (display order preserved) |
| 458 | if (cleaned.contains(' ')) |
| 459 | return parseHexBytes(cleaned, 2, ok); |
| 460 | // Single value → native-endian |
| 461 | uint val = cleaned.toUInt(ok, 16); |
| 462 | if (*ok && val > 0xFFFF) *ok = false; |
| 463 | return *ok ? toBytes<uint16_t>(static_cast<uint16_t>(val)) : QByteArray{}; |
| 464 | } |
| 465 | case NodeKind::Hex32: { |
| 466 | QString cleaned = stripHex(s); |
| 467 | // Space-separated bytes → raw byte order (display order preserved) |
| 468 | if (cleaned.contains(' ')) |
| 469 | return parseHexBytes(cleaned, 4, ok); |
| 470 | // Single value → native-endian |
| 471 | uint val = cleaned.toUInt(ok, 16); |
| 472 | return *ok ? toBytes<uint32_t>(val) : QByteArray{}; |
| 473 | } |
| 474 | case NodeKind::Hex64: { |
| 475 | QString cleaned = stripHex(s); |
| 476 | // Space-separated bytes → raw byte order (display order preserved) |
| 477 | if (cleaned.contains(' ')) |
| 478 | return parseHexBytes(cleaned, 8, ok); |
| 479 | // Single value → native-endian |
| 480 | qulonglong val = cleaned.toULongLong(ok, 16); |
| 481 | return *ok ? toBytes<uint64_t>(val) : QByteArray{}; |
| 482 | } |
| 483 | case NodeKind::Int8: { |
| 484 | bool isHex = s.startsWith("0x", Qt::CaseInsensitive); |
| 485 | if (isHex) { |
| 486 | uint val = stripHex(s).toUInt(ok, 16); |
| 487 | if (*ok && val > 0xFF) *ok = false; |
| 488 | return *ok ? toBytes<int8_t>(static_cast<int8_t>(val)) : QByteArray{}; |
| 489 | } else { |
| 490 | int val = s.toInt(ok, 10); |
| 491 | return parseIntChecked<int8_t>(val, ok); |
| 492 | } |
| 493 | } |
| 494 | case NodeKind::Int16: { |
| 495 | bool isHex = s.startsWith("0x", Qt::CaseInsensitive); |
| 496 | if (isHex) { |
| 497 | uint val = stripHex(s).toUInt(ok, 16); |