printable.cpp 4.3 KB

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