|
9 | 9 | #include <util/strencodings.h>
|
10 | 10 |
|
11 | 11 | #include <stdint.h>
|
| 12 | +#include <string> |
12 | 13 |
|
13 | 14 | #include <boost/test/unit_test.hpp>
|
14 | 15 |
|
@@ -376,4 +377,152 @@ BOOST_AUTO_TEST_CASE(class_methods)
|
376 | 377 | BOOST_CHECK(methodtest3 == methodtest4);
|
377 | 378 | }
|
378 | 379 |
|
| 380 | +enum class BaseFormat { |
| 381 | + DEC, |
| 382 | + HEX, |
| 383 | +}; |
| 384 | + |
| 385 | +/// (Un)serialize a number as a string either from/to decimal or hexadecimal. |
| 386 | +class Base |
| 387 | +{ |
| 388 | +public: |
| 389 | + uint8_t m_base_data; |
| 390 | + |
| 391 | + Base() : m_base_data(17) {} |
| 392 | + explicit Base(uint8_t data) : m_base_data(data) {} |
| 393 | + |
| 394 | +#if 0 // the following two are equivalent |
| 395 | + SERIALIZE_METHODS_PARAMS(Base, obj, BaseFormat, fmt) |
| 396 | + { |
| 397 | + if (ser_action.ForRead()) { |
| 398 | + std::string str; |
| 399 | + s >> str; |
| 400 | + const int base = fmt == BaseFormat::DEC ? 10 : 16; |
| 401 | + const uint8_t data = (uint8_t)std::stoul(str, 0, base); |
| 402 | + SER_READ(obj, obj.m_base_data = data); |
| 403 | + } else { |
| 404 | + s << strprintf(fmt == BaseFormat::DEC ? "%02hhu" : "%02hhX", obj.m_base_data); |
| 405 | + } |
| 406 | + } |
| 407 | +#else |
| 408 | + template <typename Stream> |
| 409 | + void Serialize(Stream& s) const |
| 410 | + { |
| 411 | + s << strprintf(s.GetParams() == BaseFormat::DEC ? "%02hhu" : "%02hhX", m_base_data); |
| 412 | + } |
| 413 | + |
| 414 | + template <typename Stream> |
| 415 | + void Unserialize(Stream& s) |
| 416 | + { |
| 417 | + std::string str; |
| 418 | + s >> str; |
| 419 | + const int base = s.GetParams() == BaseFormat::DEC ? 10 : 16; |
| 420 | + m_base_data = (uint8_t)std::stoul(str, 0, base); |
| 421 | + } |
| 422 | +#endif |
| 423 | +}; |
| 424 | + |
| 425 | +class DerivedAndBaseFormat |
| 426 | +{ |
| 427 | +public: |
| 428 | + BaseFormat m_base_format; |
| 429 | + |
| 430 | + enum class DerivedFormat { |
| 431 | + LOWER, |
| 432 | + UPPER, |
| 433 | + } m_derived_format; |
| 434 | +}; |
| 435 | + |
| 436 | +class Derived : public Base |
| 437 | +{ |
| 438 | +public: |
| 439 | + std::string m_derived_data; |
| 440 | + |
| 441 | + SERIALIZE_METHODS_PARAMS(Derived, obj, DerivedAndBaseFormat, fmt) |
| 442 | + { |
| 443 | + READWRITE(WithParams(fmt.m_base_format, AsBase<Base>(obj))); |
| 444 | + |
| 445 | + if (ser_action.ForRead()) { |
| 446 | + std::string str; |
| 447 | + s >> str; |
| 448 | + SER_READ(obj, obj.m_derived_data = str); |
| 449 | + } else { |
| 450 | + s << (fmt.m_derived_format == DerivedAndBaseFormat::DerivedFormat::LOWER ? |
| 451 | + ToLower(obj.m_derived_data) : |
| 452 | + ToUpper(obj.m_derived_data)); |
| 453 | + } |
| 454 | + } |
| 455 | +}; |
| 456 | + |
| 457 | +BOOST_AUTO_TEST_CASE(with_params_base) |
| 458 | +{ |
| 459 | + Base b{15}; |
| 460 | + |
| 461 | + CDataStream stream(SER_DISK, PROTOCOL_VERSION); |
| 462 | + |
| 463 | + stream << WithParams(BaseFormat::DEC, b); |
| 464 | + BOOST_CHECK_EQUAL(stream.str(), "\2" "15"); |
| 465 | + |
| 466 | + b.m_base_data = 0; |
| 467 | + stream >> WithParams(BaseFormat::DEC, b); |
| 468 | + BOOST_CHECK_EQUAL(b.m_base_data, 15); |
| 469 | + |
| 470 | + stream.clear(); |
| 471 | + |
| 472 | + stream << WithParams(BaseFormat::HEX, b); |
| 473 | + BOOST_CHECK_EQUAL(stream.str(), "\2" "0F"); |
| 474 | + |
| 475 | + b.m_base_data = 0; |
| 476 | + stream >> WithParams(BaseFormat::HEX, b); |
| 477 | + BOOST_CHECK_EQUAL(b.m_base_data, 0x0F); |
| 478 | +} |
| 479 | + |
| 480 | +BOOST_AUTO_TEST_CASE(with_params_vector_of_base) |
| 481 | +{ |
| 482 | + std::vector<Base> v{Base{15}, Base{255}}; |
| 483 | + |
| 484 | + CDataStream stream(SER_DISK, PROTOCOL_VERSION); |
| 485 | + |
| 486 | + stream << WithParams(BaseFormat::DEC, v); |
| 487 | + BOOST_CHECK_EQUAL(stream.str(), "\2\2" "15" "\3" "255"); |
| 488 | + |
| 489 | + v[0].m_base_data = 0; |
| 490 | + v[1].m_base_data = 0; |
| 491 | + stream >> WithParams(BaseFormat::DEC, v); |
| 492 | + BOOST_CHECK_EQUAL(v[0].m_base_data, 15); |
| 493 | + BOOST_CHECK_EQUAL(v[1].m_base_data, 255); |
| 494 | + |
| 495 | + stream.clear(); |
| 496 | + |
| 497 | + stream << WithParams(BaseFormat::HEX, v); |
| 498 | + BOOST_CHECK_EQUAL(stream.str(), "\2\2" "0F" "\2" "FF"); |
| 499 | + |
| 500 | + v[0].m_base_data = 0; |
| 501 | + v[1].m_base_data = 0; |
| 502 | + stream >> WithParams(BaseFormat::HEX, v); |
| 503 | + BOOST_CHECK_EQUAL(v[0].m_base_data, 0x0F); |
| 504 | + BOOST_CHECK_EQUAL(v[1].m_base_data, 0xFF); |
| 505 | +} |
| 506 | + |
| 507 | +BOOST_AUTO_TEST_CASE(with_params_derived) |
| 508 | +{ |
| 509 | + Derived d; |
| 510 | + d.m_base_data = 15; |
| 511 | + d.m_derived_data = "xY"; |
| 512 | + |
| 513 | + DerivedAndBaseFormat fmt; |
| 514 | + |
| 515 | + CDataStream stream(SER_DISK, PROTOCOL_VERSION); |
| 516 | + |
| 517 | + fmt.m_base_format = BaseFormat::DEC; |
| 518 | + fmt.m_derived_format = DerivedAndBaseFormat::DerivedFormat::LOWER; |
| 519 | + stream << WithParams(fmt, d); |
| 520 | + |
| 521 | + fmt.m_base_format = BaseFormat::HEX; |
| 522 | + fmt.m_derived_format = DerivedAndBaseFormat::DerivedFormat::UPPER; |
| 523 | + stream << WithParams(fmt, d); |
| 524 | + |
| 525 | + BOOST_CHECK_EQUAL(stream.str(), "\2" "15" "\2" "xy" "\2" "0F" "\2" "XY"); |
| 526 | +} |
| 527 | + |
379 | 528 | BOOST_AUTO_TEST_SUITE_END()
|
0 commit comments