printable.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2022, Benoit BLANCHON
  3. // MIT License
  4. #include <Arduino.h>
  5. #include <catch.hpp>
  6. #define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
  7. #include <ArduinoJson.h>
  8. struct PrintOneCharacterAtATime {
  9. static size_t printStringTo(const std::string& s, Print& p) {
  10. size_t result = 0;
  11. for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
  12. size_t n = p.write(uint8_t(*it));
  13. if (n == 0)
  14. break;
  15. result += n;
  16. }
  17. return result;
  18. }
  19. };
  20. struct PrintAllAtOnce {
  21. static size_t printStringTo(const std::string& s, Print& p) {
  22. return p.write(s.data(), s.size());
  23. }
  24. };
  25. template <typename PrintPolicy>
  26. struct PrintableString : public Printable {
  27. PrintableString(const char* s) : _str(s), _total(0) {}
  28. virtual size_t printTo(Print& p) const {
  29. size_t result = PrintPolicy::printStringTo(_str, p);
  30. _total += result;
  31. return result;
  32. }
  33. size_t totalBytesWritten() const {
  34. return _total;
  35. }
  36. private:
  37. std::string _str;
  38. mutable size_t _total;
  39. };
  40. TEST_CASE("Printable") {
  41. SECTION("Doesn't overflow") {
  42. StaticJsonDocument<8> doc;
  43. const char* value = "example"; // == 7 chars
  44. doc.set(666); // to make sure we override the value
  45. SECTION("Via Print::write(char)") {
  46. PrintableString<PrintOneCharacterAtATime> printable(value);
  47. CHECK(doc.set(printable) == true);
  48. CHECK(doc.as<std::string>() == value);
  49. CHECK(printable.totalBytesWritten() == 7);
  50. CHECK(doc.overflowed() == false);
  51. CHECK(doc.memoryUsage() == 8);
  52. CHECK(doc.as<JsonVariant>().memoryUsage() == 8);
  53. }
  54. SECTION("Via Print::write(const char* size_t)") {
  55. PrintableString<PrintAllAtOnce> printable(value);
  56. CHECK(doc.set(printable) == true);
  57. CHECK(doc.as<std::string>() == value);
  58. CHECK(printable.totalBytesWritten() == 7);
  59. CHECK(doc.overflowed() == false);
  60. CHECK(doc.memoryUsage() == 8);
  61. CHECK(doc.as<JsonVariant>().memoryUsage() == 8);
  62. }
  63. }
  64. SECTION("Overflows early") {
  65. StaticJsonDocument<8> doc;
  66. const char* value = "hello world"; // > 8 chars
  67. doc.set(666); // to make sure we override the value
  68. SECTION("Via Print::write(char)") {
  69. PrintableString<PrintOneCharacterAtATime> printable(value);
  70. CHECK(doc.set(printable) == false);
  71. CHECK(doc.isNull());
  72. CHECK(printable.totalBytesWritten() == 8);
  73. CHECK(doc.overflowed() == true);
  74. CHECK(doc.memoryUsage() == 0);
  75. }
  76. SECTION("Via Print::write(const char*, size_t)") {
  77. PrintableString<PrintAllAtOnce> printable(value);
  78. CHECK(doc.set(printable) == false);
  79. CHECK(doc.isNull());
  80. CHECK(printable.totalBytesWritten() == 0);
  81. CHECK(doc.overflowed() == true);
  82. CHECK(doc.memoryUsage() == 0);
  83. }
  84. }
  85. SECTION("Overflows adding terminator") {
  86. StaticJsonDocument<8> doc;
  87. const char* value = "overflow"; // == 8 chars
  88. doc.set(666); // to make sure we override the value
  89. SECTION("Via Print::write(char)") {
  90. PrintableString<PrintOneCharacterAtATime> printable(value);
  91. CHECK(doc.set(printable) == false);
  92. CHECK(doc.isNull());
  93. CHECK(printable.totalBytesWritten() == 8);
  94. CHECK(doc.overflowed() == true);
  95. CHECK(doc.memoryUsage() == 0);
  96. }
  97. SECTION("Via Print::write(const char*, size_t)") {
  98. PrintableString<PrintAllAtOnce> printable(value);
  99. CHECK(doc.set(printable) == false);
  100. CHECK(doc.isNull());
  101. CHECK(printable.totalBytesWritten() == 0);
  102. CHECK(doc.overflowed() == true);
  103. CHECK(doc.memoryUsage() == 0);
  104. }
  105. }
  106. SECTION("Null variant") {
  107. JsonVariant var;
  108. PrintableString<PrintOneCharacterAtATime> printable = "Hello World!";
  109. CHECK(var.set(printable) == false);
  110. CHECK(var.isNull());
  111. CHECK(printable.totalBytesWritten() == 0);
  112. }
  113. SECTION("String deduplication") {
  114. StaticJsonDocument<128> doc;
  115. doc.add(PrintableString<PrintOneCharacterAtATime>("Hello World!"));
  116. doc.add(PrintableString<PrintAllAtOnce>("Hello World!"));
  117. REQUIRE(doc.size() == 2);
  118. CHECK(doc[0] == "Hello World!");
  119. CHECK(doc[1] == "Hello World!");
  120. CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 13);
  121. }
  122. }