StringAdapters.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2025, Benoit BLANCHON
  3. // MIT License
  4. #include <Arduino.h>
  5. #include <ArduinoJson/Strings/IsString.hpp>
  6. #include <ArduinoJson/Strings/JsonString.hpp>
  7. #include <ArduinoJson/Strings/StringAdapters.hpp>
  8. #include <catch.hpp>
  9. #include "custom_string.hpp"
  10. #include "weird_strcmp.hpp"
  11. using ArduinoJson::JsonString;
  12. using namespace ArduinoJson::detail;
  13. TEST_CASE("adaptString()") {
  14. SECTION("string literal") {
  15. auto s = adaptString("bravo\0alpha");
  16. CHECK(s.isNull() == false);
  17. CHECK(s.size() == 5);
  18. CHECK(s.isStatic() == true);
  19. }
  20. SECTION("null const char*") {
  21. auto s = adaptString(static_cast<const char*>(0));
  22. CHECK(s.isNull() == true);
  23. CHECK(s.size() == 0);
  24. }
  25. SECTION("non-null const char*") {
  26. const char* p = "bravo";
  27. auto s = adaptString(p);
  28. CHECK(s.isNull() == false);
  29. CHECK(s.size() == 5);
  30. CHECK(s.isStatic() == false);
  31. CHECK(s.data() == p);
  32. }
  33. SECTION("null const char* + size") {
  34. auto s = adaptString(static_cast<const char*>(0), 10);
  35. CHECK(s.isNull() == true);
  36. CHECK(s.isStatic() == false);
  37. }
  38. SECTION("non-null const char* + size") {
  39. auto s = adaptString("bravo", 5);
  40. CHECK(s.isNull() == false);
  41. CHECK(s.size() == 5);
  42. CHECK(s.isStatic() == false);
  43. }
  44. SECTION("null Flash string") {
  45. auto s = adaptString(static_cast<const __FlashStringHelper*>(0));
  46. CHECK(s.isNull() == true);
  47. CHECK(s.size() == 0);
  48. CHECK(s.isStatic() == false);
  49. }
  50. SECTION("non-null Flash string") {
  51. auto s = adaptString(F("bravo"));
  52. CHECK(s.isNull() == false);
  53. CHECK(s.size() == 5);
  54. CHECK(s.isStatic() == false);
  55. }
  56. SECTION("std::string") {
  57. std::string orig("bravo");
  58. auto s = adaptString(orig);
  59. CHECK(s.isNull() == false);
  60. CHECK(s.size() == 5);
  61. CHECK(s.isStatic() == false);
  62. }
  63. SECTION("Arduino String") {
  64. ::String orig("bravo");
  65. auto s = adaptString(orig);
  66. CHECK(s.isNull() == false);
  67. CHECK(s.size() == 5);
  68. CHECK(s.isStatic() == false);
  69. }
  70. SECTION("custom_string") {
  71. custom_string orig("bravo");
  72. auto s = adaptString(orig);
  73. CHECK(s.isNull() == false);
  74. CHECK(s.size() == 5);
  75. CHECK(s.isStatic() == false);
  76. }
  77. SECTION("JsonString linked") {
  78. JsonString orig("hello", true);
  79. auto s = adaptString(orig);
  80. CHECK(s.isNull() == false);
  81. CHECK(s.size() == 5);
  82. CHECK(s.isStatic() == true);
  83. }
  84. SECTION("JsonString copied") {
  85. JsonString orig("hello", false);
  86. auto s = adaptString(orig);
  87. CHECK(s.isNull() == false);
  88. CHECK(s.size() == 5);
  89. CHECK(s.isStatic() == false);
  90. }
  91. }
  92. struct EmptyStruct {};
  93. TEST_CASE("IsString<T>") {
  94. CHECK(IsString<std::string>::value == true);
  95. CHECK(IsString<std::basic_string<wchar_t>>::value == false);
  96. CHECK(IsString<custom_string>::value == true);
  97. CHECK(IsString<const __FlashStringHelper*>::value == true);
  98. CHECK(IsString<const char*>::value == true);
  99. CHECK(IsString<const char[8]>::value == true);
  100. CHECK(IsString<const char[]>::value == true);
  101. CHECK(IsString<::String>::value == true);
  102. CHECK(IsString<::StringSumHelper>::value == true);
  103. CHECK(IsString<const EmptyStruct*>::value == false);
  104. CHECK(IsString<JsonString>::value == true);
  105. }
  106. TEST_CASE("stringCompare") {
  107. SECTION("ZeroTerminatedRamString vs ZeroTerminatedRamString") {
  108. CHECK(stringCompare(adaptString("bravo"), adaptString("alpha")) > 0);
  109. CHECK(stringCompare(adaptString("bravo"), adaptString("bravo")) == 0);
  110. CHECK(stringCompare(adaptString("bravo"), adaptString("charlie")) < 0);
  111. }
  112. SECTION("ZeroTerminatedRamString vs SizedRamString") {
  113. CHECK(stringCompare(adaptString("bravo"), adaptString("alpha?", 5)) > 0);
  114. CHECK(stringCompare(adaptString("bravo"), adaptString("bravo?", 4)) > 0);
  115. CHECK(stringCompare(adaptString("bravo"), adaptString("bravo?", 5)) == 0);
  116. CHECK(stringCompare(adaptString("bravo"), adaptString("bravo?", 6)) < 0);
  117. CHECK(stringCompare(adaptString("bravo"), adaptString("charlie?", 7)) < 0);
  118. }
  119. SECTION("SizedRamString vs SizedRamString") {
  120. // clang-format off
  121. CHECK(stringCompare(adaptString("bravo!", 5), adaptString("alpha?", 5)) > 0);
  122. CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo?", 5)) == 0);
  123. CHECK(stringCompare(adaptString("bravo!", 5), adaptString("charlie?", 7)) < 0);
  124. CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo!", 4)) > 0);
  125. CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo!", 5)) == 0);
  126. CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo!", 6)) < 0);
  127. // clang-format on
  128. }
  129. SECTION("FlashString vs FlashString") {
  130. // clang-format off
  131. CHECK(stringCompare(adaptString(F("bravo")), adaptString(F("alpha"))) > 0);
  132. CHECK(stringCompare(adaptString(F("bravo")), adaptString(F("bravo"))) == 0);
  133. CHECK(stringCompare(adaptString(F("bravo")), adaptString(F("charlie"))) < 0);
  134. // clang-format on
  135. }
  136. SECTION("FlashString vs SizedRamString") {
  137. // clang-format off
  138. CHECK(stringCompare(adaptString(F("bravo")), adaptString("alpha?", 5)) > 0);
  139. CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo?", 5)) == 0);
  140. CHECK(stringCompare(adaptString(F("bravo")), adaptString("charlie?", 7)) < 0);
  141. CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo!", 4)) > 0);
  142. CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo!", 5)) == 0);
  143. CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo!", 6)) < 0);
  144. // clang-format on
  145. }
  146. SECTION("ZeroTerminatedRamString vs FlashString") {
  147. // clang-format off
  148. CHECK(stringCompare(adaptString("bravo"), adaptString(F("alpha?"), 5)) > 0);
  149. CHECK(stringCompare(adaptString("bravo"), adaptString(F("bravo?"), 4)) > 0);
  150. CHECK(stringCompare(adaptString("bravo"), adaptString(F("bravo?"), 5)) == 0);
  151. CHECK(stringCompare(adaptString("bravo"), adaptString(F("bravo?"), 6)) < 0);
  152. CHECK(stringCompare(adaptString("bravo"), adaptString(F("charlie?"), 7)) < 0);
  153. // clang-format on
  154. }
  155. }
  156. TEST_CASE("stringEquals()") {
  157. SECTION("ZeroTerminatedRamString vs ZeroTerminatedRamString") {
  158. CHECK(stringEquals(adaptString("bravo"), adaptString("brav")) == false);
  159. CHECK(stringEquals(adaptString("bravo"), adaptString("bravo")) == true);
  160. CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!")) == false);
  161. }
  162. SECTION("ZeroTerminatedRamString vs SizedRamString") {
  163. // clang-format off
  164. CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!", 4)) == false);
  165. CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!", 5)) == true);
  166. CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!", 6)) == false);
  167. // clang-format on
  168. }
  169. SECTION("FlashString vs SizedRamString") {
  170. // clang-format off
  171. CHECK(stringEquals(adaptString(F("bravo")), adaptString("bravo!", 4)) == false);
  172. CHECK(stringEquals(adaptString(F("bravo")), adaptString("bravo!", 5)) == true);
  173. CHECK(stringEquals(adaptString(F("bravo")), adaptString("bravo!", 6)) == false);
  174. // clang-format on
  175. }
  176. SECTION("SizedRamString vs SizedRamString") {
  177. // clang-format off
  178. CHECK(stringEquals(adaptString("bravo?", 5), adaptString("bravo!", 4)) == false);
  179. CHECK(stringEquals(adaptString("bravo?", 5), adaptString("bravo!", 5)) == true);
  180. CHECK(stringEquals(adaptString("bravo?", 5), adaptString("bravo!", 6)) == false);
  181. // clang-format on
  182. }
  183. }