subscript.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2023, Benoit BLANCHON
  3. // MIT License
  4. #include <ArduinoJson.h>
  5. #include <catch.hpp>
  6. #include "Allocators.hpp"
  7. using ArduinoJson::detail::sizeofObject;
  8. using ArduinoJson::detail::sizeofString;
  9. TEST_CASE("JsonObject::operator[]") {
  10. SpyingAllocator allocator;
  11. JsonDocument doc(&allocator);
  12. JsonObject obj = doc.to<JsonObject>();
  13. SECTION("int") {
  14. obj["hello"] = 123;
  15. REQUIRE(123 == obj["hello"].as<int>());
  16. REQUIRE(true == obj["hello"].is<int>());
  17. REQUIRE(false == obj["hello"].is<bool>());
  18. }
  19. SECTION("volatile int") { // issue #415
  20. volatile int i = 123;
  21. obj["hello"] = i;
  22. REQUIRE(123 == obj["hello"].as<int>());
  23. REQUIRE(true == obj["hello"].is<int>());
  24. REQUIRE(false == obj["hello"].is<bool>());
  25. }
  26. SECTION("double") {
  27. obj["hello"] = 123.45;
  28. REQUIRE(true == obj["hello"].is<double>());
  29. REQUIRE(false == obj["hello"].is<long>());
  30. REQUIRE(123.45 == obj["hello"].as<double>());
  31. }
  32. SECTION("bool") {
  33. obj["hello"] = true;
  34. REQUIRE(true == obj["hello"].is<bool>());
  35. REQUIRE(false == obj["hello"].is<long>());
  36. REQUIRE(true == obj["hello"].as<bool>());
  37. }
  38. SECTION("const char*") {
  39. obj["hello"] = "h3110";
  40. REQUIRE(true == obj["hello"].is<const char*>());
  41. REQUIRE(false == obj["hello"].is<long>());
  42. REQUIRE(std::string("h3110") == obj["hello"].as<const char*>());
  43. }
  44. SECTION("array") {
  45. JsonDocument doc2;
  46. JsonArray arr = doc2.to<JsonArray>();
  47. obj["hello"] = arr;
  48. REQUIRE(arr == obj["hello"].as<JsonArray>());
  49. REQUIRE(true == obj["hello"].is<JsonArray>());
  50. REQUIRE(false == obj["hello"].is<JsonObject>());
  51. }
  52. SECTION("object") {
  53. JsonDocument doc2;
  54. JsonObject obj2 = doc2.to<JsonObject>();
  55. obj["hello"] = obj2;
  56. REQUIRE(obj2 == obj["hello"].as<JsonObject>());
  57. REQUIRE(true == obj["hello"].is<JsonObject>());
  58. REQUIRE(false == obj["hello"].is<JsonArray>());
  59. }
  60. SECTION("array subscript") {
  61. JsonDocument doc2;
  62. JsonArray arr = doc2.to<JsonArray>();
  63. arr.add(42);
  64. obj["a"] = arr[0];
  65. REQUIRE(42 == obj["a"]);
  66. }
  67. SECTION("object subscript") {
  68. JsonDocument doc2;
  69. JsonObject obj2 = doc2.to<JsonObject>();
  70. obj2["x"] = 42;
  71. obj["a"] = obj2["x"];
  72. REQUIRE(42 == obj["a"]);
  73. }
  74. SECTION("char key[]") { // issue #423
  75. char key[] = "hello";
  76. obj[key] = 42;
  77. REQUIRE(42 == obj[key]);
  78. }
  79. SECTION("should not duplicate const char*") {
  80. obj["hello"] = "world";
  81. REQUIRE(allocator.log() == AllocatorLog()
  82. << AllocatorLog::Allocate(sizeofPool()));
  83. }
  84. SECTION("should duplicate char* value") {
  85. obj["hello"] = const_cast<char*>("world");
  86. REQUIRE(allocator.log() == AllocatorLog()
  87. << AllocatorLog::Allocate(sizeofPool())
  88. << AllocatorLog::Allocate(sizeofString(5)));
  89. }
  90. SECTION("should duplicate char* key") {
  91. obj[const_cast<char*>("hello")] = "world";
  92. REQUIRE(allocator.log() == AllocatorLog()
  93. << AllocatorLog::Allocate(sizeofString(5))
  94. << AllocatorLog::Allocate(sizeofPool()));
  95. }
  96. SECTION("should duplicate char* key&value") {
  97. obj[const_cast<char*>("hello")] = const_cast<char*>("world");
  98. REQUIRE(allocator.log() == AllocatorLog()
  99. << AllocatorLog::Allocate(sizeofString(5))
  100. << AllocatorLog::Allocate(sizeofPool())
  101. << AllocatorLog::Allocate(sizeofString(5)));
  102. }
  103. SECTION("should duplicate std::string value") {
  104. obj["hello"] = std::string("world");
  105. REQUIRE(allocator.log() == AllocatorLog()
  106. << AllocatorLog::Allocate(sizeofPool())
  107. << AllocatorLog::Allocate(sizeofString(5)));
  108. }
  109. SECTION("should duplicate std::string key") {
  110. obj[std::string("hello")] = "world";
  111. REQUIRE(allocator.log() == AllocatorLog()
  112. << AllocatorLog::Allocate(sizeofString(5))
  113. << AllocatorLog::Allocate(sizeofPool()));
  114. }
  115. SECTION("should duplicate std::string key&value") {
  116. obj[std::string("hello")] = std::string("world");
  117. REQUIRE(allocator.log() == AllocatorLog()
  118. << AllocatorLog::Allocate(sizeofString(5))
  119. << AllocatorLog::Allocate(sizeofPool())
  120. << AllocatorLog::Allocate(sizeofString(5)));
  121. }
  122. SECTION("should duplicate a non-static JsonString key") {
  123. obj[JsonString("hello", JsonString::Copied)] = "world";
  124. REQUIRE(allocator.log() == AllocatorLog()
  125. << AllocatorLog::Allocate(sizeofString(5))
  126. << AllocatorLog::Allocate(sizeofPool()));
  127. }
  128. SECTION("should not duplicate a static JsonString key") {
  129. obj[JsonString("hello", JsonString::Linked)] = "world";
  130. REQUIRE(allocator.log() == AllocatorLog()
  131. << AllocatorLog::Allocate(sizeofPool()));
  132. }
  133. SECTION("should ignore null key") {
  134. // object must have a value to make a call to strcmp()
  135. obj["dummy"] = 42;
  136. const char* null = 0;
  137. obj[null] = 666;
  138. REQUIRE(obj.size() == 1);
  139. REQUIRE(obj[null] == null);
  140. }
  141. SECTION("obj[key].to<JsonArray>()") {
  142. JsonArray arr = obj["hello"].to<JsonArray>();
  143. REQUIRE(arr.isNull() == false);
  144. }
  145. #if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
  146. !defined(SUBSCRIPT_CONFLICTS_WITH_BUILTIN_OPERATOR)
  147. SECTION("obj[VLA] = str") {
  148. size_t i = 16;
  149. char vla[i];
  150. strcpy(vla, "hello");
  151. obj[vla] = "world";
  152. REQUIRE(std::string("world") == obj["hello"]);
  153. }
  154. SECTION("obj[str] = VLA") { // issue #416
  155. size_t i = 32;
  156. char vla[i];
  157. strcpy(vla, "world");
  158. obj["hello"] = vla;
  159. REQUIRE(std::string("world") == obj["hello"].as<const char*>());
  160. }
  161. SECTION("obj.set(VLA, str)") {
  162. size_t i = 16;
  163. char vla[i];
  164. strcpy(vla, "hello");
  165. obj[vla] = "world";
  166. REQUIRE(std::string("world") == obj["hello"]);
  167. }
  168. SECTION("obj.set(str, VLA)") {
  169. size_t i = 32;
  170. char vla[i];
  171. strcpy(vla, "world");
  172. obj["hello"].set(vla);
  173. REQUIRE(std::string("world") == obj["hello"].as<const char*>());
  174. }
  175. SECTION("obj[VLA]") {
  176. size_t i = 16;
  177. char vla[i];
  178. strcpy(vla, "hello");
  179. deserializeJson(doc, "{\"hello\":\"world\"}");
  180. obj = doc.as<JsonObject>();
  181. REQUIRE(std::string("world") == obj[vla]);
  182. }
  183. #endif
  184. SECTION("chain") {
  185. obj.createNestedObject("hello")["world"] = 123;
  186. REQUIRE(123 == obj["hello"]["world"].as<int>());
  187. REQUIRE(true == obj["hello"]["world"].is<int>());
  188. REQUIRE(false == obj["hello"]["world"].is<bool>());
  189. }
  190. }