printable.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright Benoit Blanchon 2014-2021
  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. }
  53. SECTION("Via Print::write(const char* size_t)") {
  54. PrintableString<PrintAllAtOnce> printable(value);
  55. CHECK(doc.set(printable) == true);
  56. CHECK(doc.as<std::string>() == value);
  57. CHECK(printable.totalBytesWritten() == 7);
  58. CHECK(doc.overflowed() == false);
  59. CHECK(doc.memoryUsage() == 8);
  60. }
  61. }
  62. SECTION("Overflows early") {
  63. StaticJsonDocument<8> doc;
  64. const char* value = "hello world"; // > 8 chars
  65. doc.set(666); // to make sure we override the value
  66. SECTION("Via Print::write(char)") {
  67. PrintableString<PrintOneCharacterAtATime> printable(value);
  68. CHECK(doc.set(printable) == false);
  69. CHECK(doc.isNull());
  70. CHECK(printable.totalBytesWritten() == 8);
  71. CHECK(doc.overflowed() == true);
  72. CHECK(doc.memoryUsage() == 0);
  73. }
  74. SECTION("Via Print::write(const char*, size_t)") {
  75. PrintableString<PrintAllAtOnce> printable(value);
  76. CHECK(doc.set(printable) == false);
  77. CHECK(doc.isNull());
  78. CHECK(printable.totalBytesWritten() == 0);
  79. CHECK(doc.overflowed() == true);
  80. CHECK(doc.memoryUsage() == 0);
  81. }
  82. }
  83. SECTION("Overflows adding terminator") {
  84. StaticJsonDocument<8> doc;
  85. const char* value = "overflow"; // == 8 chars
  86. doc.set(666); // to make sure we override the value
  87. SECTION("Via Print::write(char)") {
  88. PrintableString<PrintOneCharacterAtATime> printable(value);
  89. CHECK(doc.set(printable) == false);
  90. CHECK(doc.isNull());
  91. CHECK(printable.totalBytesWritten() == 8);
  92. CHECK(doc.overflowed() == true);
  93. CHECK(doc.memoryUsage() == 0);
  94. }
  95. SECTION("Via Print::write(const char*, size_t)") {
  96. PrintableString<PrintAllAtOnce> printable(value);
  97. CHECK(doc.set(printable) == false);
  98. CHECK(doc.isNull());
  99. CHECK(printable.totalBytesWritten() == 0);
  100. CHECK(doc.overflowed() == true);
  101. CHECK(doc.memoryUsage() == 0);
  102. }
  103. }
  104. SECTION("Null variant") {
  105. JsonVariant var;
  106. PrintableString<PrintOneCharacterAtATime> printable = "Hello World!";
  107. CHECK(var.set(printable) == false);
  108. CHECK(var.isNull());
  109. CHECK(printable.totalBytesWritten() == 0);
  110. }
  111. SECTION("String deduplication") {
  112. StaticJsonDocument<128> doc;
  113. doc.add(PrintableString<PrintOneCharacterAtATime>("Hello World!"));
  114. doc.add(PrintableString<PrintAllAtOnce>("Hello World!"));
  115. REQUIRE(doc.size() == 2);
  116. CHECK(doc[0] == "Hello World!");
  117. CHECK(doc[1] == "Hello World!");
  118. CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 13);
  119. }
  120. }