mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	JsonVariant automatically promotes to JsonObject or JsonArray on write
This commit is contained in:
		| @@ -22,6 +22,12 @@ HEAD | |||||||
| * Added `JsonDocument::operator[]` | * Added `JsonDocument::operator[]` | ||||||
| * Added `ARDUINOJSON_TAB` to configure the indentation character | * Added `ARDUINOJSON_TAB` to configure the indentation character | ||||||
| * Reduced the size of the pretty JSON serializer | * Reduced the size of the pretty JSON serializer | ||||||
|  | * Added `add()`, `createNestedArray()` and `createNestedObject()` to `JsonVariant` | ||||||
|  | * `JsonVariant` automatically promotes to `JsonObject` or `JsonArray` on write. | ||||||
|  |   Calling `JsonVariant::to<T>()` is not required anymore. | ||||||
|  | * `JsonDocument` now support the same operations as `JsonVariant`. | ||||||
|  |   Calling `JsonDocument::as<T>()` is not required anymore. | ||||||
|  | * Fixed example `JsonHttpClient.ino` | ||||||
|  |  | ||||||
| > ### BREAKING CHANGES | > ### BREAKING CHANGES | ||||||
| >  | >  | ||||||
|   | |||||||
| @@ -15,7 +15,11 @@ | |||||||
| #include <SD.h> | #include <SD.h> | ||||||
| #include <SPI.h> | #include <SPI.h> | ||||||
|  |  | ||||||
| // Configuration that we'll store on disk | // Our configuration structure. | ||||||
|  | // | ||||||
|  | // Never use a JsonDocument to store the configuration! | ||||||
|  | // A JsonDocument is *not* a permanent storage; it's only a temporary storage | ||||||
|  | // used during the serialization phase. | ||||||
| struct Config { | struct Config { | ||||||
|   char hostname[64]; |   char hostname[64]; | ||||||
|   int port; |   int port; | ||||||
| @@ -29,9 +33,9 @@ void loadConfiguration(const char *filename, Config &config) { | |||||||
|   // Open file for reading |   // Open file for reading | ||||||
|   File file = SD.open(filename); |   File file = SD.open(filename); | ||||||
|  |  | ||||||
|   // Allocate the document on the stack. |   // Allocate a temporary JsonDocument | ||||||
|   // Don't forget to change the capacity to match your requirements. |   // Don't forget to change the capacity to match your requirements. | ||||||
|   // Use arduinojson.org/assistant to compute the capacity. |   // Use arduinojson.org/v6/assistant to compute the capacity. | ||||||
|   StaticJsonDocument<512> doc; |   StaticJsonDocument<512> doc; | ||||||
|  |  | ||||||
|   // Deserialize the JSON document |   // Deserialize the JSON document | ||||||
| @@ -39,16 +43,13 @@ void loadConfiguration(const char *filename, Config &config) { | |||||||
|   if (error) |   if (error) | ||||||
|     Serial.println(F("Failed to read file, using default configuration")); |     Serial.println(F("Failed to read file, using default configuration")); | ||||||
|  |  | ||||||
|   // Get the root object in the document |   // Copy values from the JsonDocument to the Config | ||||||
|   JsonObject root = doc.as<JsonObject>(); |   config.port = doc["port"] | 2731; | ||||||
|  |  | ||||||
|   // Copy values from the JsonObject to the Config |  | ||||||
|   config.port = root["port"] | 2731; |  | ||||||
|   strlcpy(config.hostname,                  // <- destination |   strlcpy(config.hostname,                  // <- destination | ||||||
|           root["hostname"] | "example.com",  // <- source |           doc["hostname"] | "example.com",  // <- source | ||||||
|           sizeof(config.hostname));         // <- destination's capacity |           sizeof(config.hostname));         // <- destination's capacity | ||||||
|  |  | ||||||
|   // Close the file (File's destructor doesn't close the file) |   // Close the file (Curiously, File's destructor doesn't close the file) | ||||||
|   file.close(); |   file.close(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -64,24 +65,21 @@ void saveConfiguration(const char *filename, const Config &config) { | |||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Allocate the document on the stack. |   // Allocate a temporary JsonDocument | ||||||
|   // Don't forget to change the capacity to match your requirements. |   // Don't forget to change the capacity to match your requirements. | ||||||
|   // Use arduinojson.org/assistant to compute the capacity. |   // Use arduinojson.org/assistant to compute the capacity. | ||||||
|   StaticJsonDocument<256> doc; |   StaticJsonDocument<256> doc; | ||||||
|  |  | ||||||
|   // Make our document contain an object |   // Set the values in the document | ||||||
|   JsonObject root = doc.to<JsonObject>(); |   doc["hostname"] = config.hostname; | ||||||
|  |   doc["port"] = config.port; | ||||||
|   // Set the values in the object |  | ||||||
|   root["hostname"] = config.hostname; |  | ||||||
|   root["port"] = config.port; |  | ||||||
|  |  | ||||||
|   // Serialize JSON to file |   // Serialize JSON to file | ||||||
|   if (serializeJson(doc, file) == 0) { |   if (serializeJson(doc, file) == 0) { | ||||||
|     Serial.println(F("Failed to write to file")); |     Serial.println(F("Failed to write to file")); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Close the file (File's destructor doesn't close the file) |   // Close the file | ||||||
|   file.close(); |   file.close(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -100,7 +98,7 @@ void printFile(const char *filename) { | |||||||
|   } |   } | ||||||
|   Serial.println(); |   Serial.println(); | ||||||
|  |  | ||||||
|   // Close the file (File's destructor doesn't close the file) |   // Close the file | ||||||
|   file.close(); |   file.close(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ void setup() { | |||||||
|   // |   // | ||||||
|   // Inside the brackets, 200 is the RAM allocated to this document. |   // Inside the brackets, 200 is the RAM allocated to this document. | ||||||
|   // Don't forget to change this value to match your requirement. |   // Don't forget to change this value to match your requirement. | ||||||
|   // Use arduinojson.org/assistant to compute the capacity. |   // Use arduinojson.org/v6/assistant to compute the capacity. | ||||||
|   StaticJsonDocument<200> doc; |   StaticJsonDocument<200> doc; | ||||||
|  |  | ||||||
|   // StaticJsonObject allocates memory on the stack, it can be |   // StaticJsonObject allocates memory on the stack, it can be | ||||||
| @@ -23,30 +23,30 @@ void setup() { | |||||||
|   // |   // | ||||||
|   // DynamicJsonDocument  doc(200); |   // DynamicJsonDocument  doc(200); | ||||||
|  |  | ||||||
|   // Make our document be an object |   // Add values in the document | ||||||
|   JsonObject root = doc.to<JsonObject>(); |  | ||||||
|  |  | ||||||
|   // Add values in the object |  | ||||||
|   // |   // | ||||||
|   // Most of the time, you can rely on the implicit casts. |   doc["sensor"] = "gps"; | ||||||
|   // In other case, you can do root.set<long>("time", 1351824120); |   doc["time"] = 1351824120; | ||||||
|   root["sensor"] = "gps"; |  | ||||||
|   root["time"] = 1351824120; |  | ||||||
|  |  | ||||||
|   // Add an array. |   // Add an array. | ||||||
|   // |   // | ||||||
|   JsonArray data = root.createNestedArray("data"); |   JsonArray data = doc.createNestedArray("data"); | ||||||
|   data.add(48.756080); |   data.add(48.756080); | ||||||
|   data.add(2.302038); |   data.add(2.302038); | ||||||
|  |  | ||||||
|  |   // Generate the minified JSON and send it to the Serial port. | ||||||
|  |   // | ||||||
|   serializeJson(doc, Serial); |   serializeJson(doc, Serial); | ||||||
|   // This prints: |   // The above line prints: | ||||||
|   // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} |   // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} | ||||||
|  |  | ||||||
|  |   // Start a new line | ||||||
|   Serial.println(); |   Serial.println(); | ||||||
|  |  | ||||||
|  |   // Generate the prettified JSON and send it to the Serial port. | ||||||
|  |   // | ||||||
|   serializeJsonPretty(doc, Serial); |   serializeJsonPretty(doc, Serial); | ||||||
|   // This prints: |   // The above line prints: | ||||||
|   // { |   // { | ||||||
|   //   "sensor": "gps", |   //   "sensor": "gps", | ||||||
|   //   "time": 1351824120, |   //   "time": 1351824120, | ||||||
|   | |||||||
| @@ -71,7 +71,7 @@ void setup() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Allocate the JSON document |   // Allocate the JSON document | ||||||
|   // Use arduinojson.org/assistant to compute the capacity. |   // Use arduinojson.org/v6/assistant to compute the capacity. | ||||||
|   const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60; |   const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60; | ||||||
|   DynamicJsonDocument doc(capacity); |   DynamicJsonDocument doc(capacity); | ||||||
|  |  | ||||||
| @@ -84,12 +84,11 @@ void setup() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Extract values |   // Extract values | ||||||
|   JsonObject root = doc.as<JsonObject>(); |  | ||||||
|   Serial.println(F("Response:")); |   Serial.println(F("Response:")); | ||||||
|   Serial.println(root["sensor"].as<char*>()); |   Serial.println(doc["sensor"].as<char*>()); | ||||||
|   Serial.println(root["time"].as<char*>()); |   Serial.println(doc["time"].as<long>()); | ||||||
|   Serial.println(root["data"][0].as<char*>()); |   Serial.println(doc["data"][0].as<float>(), 6); | ||||||
|   Serial.println(root["data"][1].as<char*>()); |   Serial.println(doc["data"][1].as<float>(), 6); | ||||||
|  |  | ||||||
|   // Disconnect |   // Disconnect | ||||||
|   client.stop(); |   client.stop(); | ||||||
|   | |||||||
| @@ -13,9 +13,9 @@ void setup() { | |||||||
|  |  | ||||||
|   // Allocate the JSON document |   // Allocate the JSON document | ||||||
|   // |   // | ||||||
|   // Inside the brackets, 200 is the size of the memory pool in bytes. |   // Inside the brackets, 200 is the capacity of the memory pool in bytes. | ||||||
|   // Don't forget to change this value to match your JSON document. |   // Don't forget to change this value to match your JSON document. | ||||||
|   // Use arduinojson.org/assistant to compute the capacity. |   // Use arduinojson.org/v6/assistant to compute the capacity. | ||||||
|   StaticJsonDocument<200> doc; |   StaticJsonDocument<200> doc; | ||||||
|  |  | ||||||
|   // StaticJsonDocument<N> allocates memory on the stack, it can be |   // StaticJsonDocument<N> allocates memory on the stack, it can be | ||||||
| @@ -25,9 +25,12 @@ void setup() { | |||||||
|  |  | ||||||
|   // JSON input string. |   // JSON input string. | ||||||
|   // |   // | ||||||
|   // It's better to use a char[] as shown here. |   // Using a char[], as shown here, enables the "zero-copy" mode. This mode uses | ||||||
|   // If you use a const char* or a String, ArduinoJson will |   // the minimal amount of memory because the JsonDocument stores pointers to | ||||||
|   // have to make a copy of the input in the JsonBuffer. |   // the input buffer. | ||||||
|  |   // If you use another type of input, ArduinoJson must copy the strings from | ||||||
|  |   // the input to the JsonDocument, so you need to increase the capacity of the | ||||||
|  |   // JsonDocument. | ||||||
|   char json[] = |   char json[] = | ||||||
|       "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; |       "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; | ||||||
|  |  | ||||||
| @@ -41,17 +44,14 @@ void setup() { | |||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Get the root object in the document |  | ||||||
|   JsonObject root = doc.as<JsonObject>(); |  | ||||||
|  |  | ||||||
|   // Fetch values. |   // Fetch values. | ||||||
|   // |   // | ||||||
|   // Most of the time, you can rely on the implicit casts. |   // Most of the time, you can rely on the implicit casts. | ||||||
|   // In other case, you can do root["time"].as<long>(); |   // In other case, you can do doc["time"].as<long>(); | ||||||
|   const char* sensor = root["sensor"]; |   const char* sensor = doc["sensor"]; | ||||||
|   long time = root["time"]; |   long time = doc["time"]; | ||||||
|   double latitude = root["data"][0]; |   double latitude = doc["data"][0]; | ||||||
|   double longitude = root["data"][1]; |   double longitude = doc["data"][1]; | ||||||
|  |  | ||||||
|   // Print values. |   // Print values. | ||||||
|   Serial.println(sensor); |   Serial.println(sensor); | ||||||
|   | |||||||
| @@ -2,15 +2,15 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2018 | // Copyright Benoit Blanchon 2014-2018 | ||||||
| // MIT License | // MIT License | ||||||
| // | // | ||||||
| // This example shows how to implement an HTTP server that sends JSON document | // This example shows how to implement an HTTP server that sends a JSON document | ||||||
| // in the responses. | // in the response. | ||||||
| // It uses the Ethernet library but can be easily adapted for Wifi. | // It uses the Ethernet library but can be easily adapted for Wifi. | ||||||
| // | // | ||||||
| // It sends the value of the analog and digital pins. | // The JSON document contains the values of the analog and digital pins. | ||||||
| // The JSON document looks like the following: | // It looks like that: | ||||||
| // { | // { | ||||||
| //   "analog": [ 0, 1, 2, 3, 4, 5 ], | //   "analog": [0, 76, 123, 158, 192, 205], | ||||||
| //   "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ] | //   "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0] | ||||||
| // } | // } | ||||||
|  |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
| @@ -51,15 +51,12 @@ void loop() { | |||||||
|   // Read the request (we ignore the content in this example) |   // Read the request (we ignore the content in this example) | ||||||
|   while (client.available()) client.read(); |   while (client.available()) client.read(); | ||||||
|  |  | ||||||
|   // Allocate the JSON document |   // Allocate a temporary JsonDocument | ||||||
|   // Use arduinojson.org/assistant to compute the capacity. |   // Use arduinojson.org/v6/assistant to compute the capacity. | ||||||
|   StaticJsonDocument<500> doc; |   StaticJsonDocument<500> doc; | ||||||
|  |  | ||||||
|   // Make our document represent an object |  | ||||||
|   JsonObject root = doc.to<JsonObject>(); |  | ||||||
|  |  | ||||||
|   // Create the "analog" array |   // Create the "analog" array | ||||||
|   JsonArray analogValues = root.createNestedArray("analog"); |   JsonArray analogValues = doc.createNestedArray("analog"); | ||||||
|   for (int pin = 0; pin < 6; pin++) { |   for (int pin = 0; pin < 6; pin++) { | ||||||
|     // Read the analog input |     // Read the analog input | ||||||
|     int value = analogRead(pin); |     int value = analogRead(pin); | ||||||
| @@ -69,7 +66,7 @@ void loop() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Create the "digital" array |   // Create the "digital" array | ||||||
|   JsonArray digitalValues = root.createNestedArray("digital"); |   JsonArray digitalValues = doc.createNestedArray("digital"); | ||||||
|   for (int pin = 0; pin < 14; pin++) { |   for (int pin = 0; pin < 14; pin++) { | ||||||
|     // Read the digital input |     // Read the digital input | ||||||
|     int value = digitalRead(pin); |     int value = digitalRead(pin); | ||||||
| @@ -83,9 +80,11 @@ void loop() { | |||||||
|   Serial.println(); |   Serial.println(); | ||||||
|  |  | ||||||
|   // Write response headers |   // Write response headers | ||||||
|   client.println("HTTP/1.0 200 OK"); |   client.println(F("HTTP/1.0 200 OK")); | ||||||
|   client.println("Content-Type: application/json"); |   client.println(F("Content-Type: application/json")); | ||||||
|   client.println("Connection: close"); |   client.println(F("Connection: close")); | ||||||
|  |   client.print(F("Content-Length: ")); | ||||||
|  |   client.println(measureJsonPretty(doc)); | ||||||
|   client.println(); |   client.println(); | ||||||
|  |  | ||||||
|   // Write JSON document |   // Write JSON document | ||||||
|   | |||||||
| @@ -5,10 +5,10 @@ | |||||||
| // This example shows how to send a JSON document to a UDP socket. | // This example shows how to send a JSON document to a UDP socket. | ||||||
| // At regular interval, it sends a UDP packet that contains the status of | // At regular interval, it sends a UDP packet that contains the status of | ||||||
| // analog and digital pins. | // analog and digital pins. | ||||||
| // The JSON document looks like the following: | // It looks like that: | ||||||
| // { | // { | ||||||
| //   "analog": [ 0, 1, 2, 3, 4, 5 ], | //   "analog": [0, 76, 123, 158, 192, 205], | ||||||
| //   "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ] | //   "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0] | ||||||
| // } | // } | ||||||
| // | // | ||||||
| // If you want to test this program, you need to be able to receive the UDP | // If you want to test this program, you need to be able to receive the UDP | ||||||
| @@ -43,15 +43,12 @@ void setup() { | |||||||
| } | } | ||||||
|  |  | ||||||
| void loop() { | void loop() { | ||||||
|   // Allocate the JSON document |   // Allocate a temporary JsonDocument | ||||||
|   // Use arduinojson.org/assistant to compute the capacity. |   // Use arduinojson.org/v6/assistant to compute the capacity. | ||||||
|   StaticJsonDocument<500> doc; |   StaticJsonDocument<500> doc; | ||||||
|  |  | ||||||
|   // Make our document represent an object |  | ||||||
|   JsonObject root = doc.to<JsonObject>(); |  | ||||||
|  |  | ||||||
|   // Create the "analog" array |   // Create the "analog" array | ||||||
|   JsonArray analogValues = root.createNestedArray("analog"); |   JsonArray analogValues = doc.createNestedArray("analog"); | ||||||
|   for (int pin = 0; pin < 6; pin++) { |   for (int pin = 0; pin < 6; pin++) { | ||||||
|     // Read the analog input |     // Read the analog input | ||||||
|     int value = analogRead(pin); |     int value = analogRead(pin); | ||||||
| @@ -61,7 +58,7 @@ void loop() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Create the "digital" array |   // Create the "digital" array | ||||||
|   JsonArray digitalValues = root.createNestedArray("digital"); |   JsonArray digitalValues = doc.createNestedArray("digital"); | ||||||
|   for (int pin = 0; pin < 14; pin++) { |   for (int pin = 0; pin < 14; pin++) { | ||||||
|     // Read the digital input |     // Read the digital input | ||||||
|     int value = digitalRead(pin); |     int value = digitalRead(pin); | ||||||
|   | |||||||
| @@ -14,9 +14,9 @@ void setup() { | |||||||
|  |  | ||||||
|   // Allocate the JSON document |   // Allocate the JSON document | ||||||
|   // |   // | ||||||
|   // Inside the brackets, 200 is the size of the memory pool in bytes. |   // Inside the brackets, 200 is the capacity of the memory pool in bytes. | ||||||
|   // Don't forget to change this value to match your JSON document. |   // Don't forget to change this value to match your JSON document. | ||||||
|   // Use arduinojson.org/assistant to compute the capacity. |   // Use arduinojson.org/v6/assistant to compute the capacity. | ||||||
|   StaticJsonDocument<200> doc; |   StaticJsonDocument<200> doc; | ||||||
|  |  | ||||||
|   // StaticJsonObject allocates memory on the stack, it can be |   // StaticJsonObject allocates memory on the stack, it can be | ||||||
| @@ -26,9 +26,12 @@ void setup() { | |||||||
|  |  | ||||||
|   // MessagePack input string. |   // MessagePack input string. | ||||||
|   // |   // | ||||||
|   // It's better to use a char[] as shown here. |   // Using a char[], as shown here, enables the "zero-copy" mode. This mode uses | ||||||
|   // If you use a const char* or a String, ArduinoJson will |   // the minimal amount of memory because the JsonDocument stores pointers to | ||||||
|   // have to make a copy of the input in the JsonBuffer. |   // the input buffer. | ||||||
|  |   // If you use another type of input, ArduinoJson must copy the strings from | ||||||
|  |   // the input to the JsonDocument, so you need to increase the capacity of the | ||||||
|  |   // JsonDocument. | ||||||
|   uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115, |   uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115, | ||||||
|                      164, 116, 105, 109, 101, 206, 80,  147, 50,  248, 164, 100, |                      164, 116, 105, 109, 101, 206, 80,  147, 50,  248, 164, 100, | ||||||
|                      97,  116, 97,  146, 203, 64,  72,  96,  199, 58,  188, 148, |                      97,  116, 97,  146, 203, 64,  72,  96,  199, 58,  188, 148, | ||||||
| @@ -40,31 +43,23 @@ void setup() { | |||||||
|   //   "data": [48.75608, 2.302038] |   //   "data": [48.75608, 2.302038] | ||||||
|   // } |   // } | ||||||
|  |  | ||||||
|   // doc of the object tree. |  | ||||||
|   // |  | ||||||
|   // It's a reference to the JsonObject, the actual bytes are inside the |  | ||||||
|   // JsonBuffer with all the other nodes of the object tree. |  | ||||||
|   // Memory is freed when jsonBuffer goes out of scope. |  | ||||||
|   DeserializationError error = deserializeMsgPack(doc, input); |   DeserializationError error = deserializeMsgPack(doc, input); | ||||||
|  |  | ||||||
|   // Test if parsing succeeds. |   // Test if parsing succeeded. | ||||||
|   if (error) { |   if (error) { | ||||||
|     Serial.print("deserializeMsgPack() failed: "); |     Serial.print("deserializeMsgPack() failed: "); | ||||||
|     Serial.println(error.c_str()); |     Serial.println(error.c_str()); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Get the root object in the document |  | ||||||
|   JsonObject root = doc.as<JsonObject>(); |  | ||||||
|  |  | ||||||
|   // Fetch values. |   // Fetch values. | ||||||
|   // |   // | ||||||
|   // Most of the time, you can rely on the implicit casts. |   // Most of the time, you can rely on the implicit casts. | ||||||
|   // In other case, you can do root["time"].as<long>(); |   // In other case, you can do doc["time"].as<long>(); | ||||||
|   const char* sensor = root["sensor"]; |   const char* sensor = doc["sensor"]; | ||||||
|   long time = root["time"]; |   long time = doc["time"]; | ||||||
|   double latitude = root["data"][0]; |   double latitude = doc["data"][0]; | ||||||
|   double longitude = root["data"][1]; |   double longitude = doc["data"][1]; | ||||||
|  |  | ||||||
|   // Print values. |   // Print values. | ||||||
|   Serial.println(sensor); |   Serial.println(sensor); | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
| // ArduinoJson. | // ArduinoJson. | ||||||
| // | // | ||||||
| // Use Flash strings sparingly, because ArduinoJson duplicates them in the | // Use Flash strings sparingly, because ArduinoJson duplicates them in the | ||||||
| // JsonBuffer. Prefer plain old char*, as they are more efficient in term of | // JsonDocument. Prefer plain old char*, as they are more efficient in term of | ||||||
| // code size, speed, and memory usage. | // code size, speed, and memory usage. | ||||||
|  |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
| @@ -17,8 +17,7 @@ void setup() { | |||||||
|   DynamicJsonDocument doc(1024); |   DynamicJsonDocument doc(1024); | ||||||
|  |  | ||||||
|   // You can use a Flash String as your JSON input. |   // You can use a Flash String as your JSON input. | ||||||
|   // WARNING: the content of the Flash String will be duplicated in the |   // WARNING: the string in the input  will be duplicated in the JsonDocument. | ||||||
|   // JsonBuffer. |  | ||||||
|   deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120," |   deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120," | ||||||
|                          "\"data\":[48.756080,2.302038]}")); |                          "\"data\":[48.756080,2.302038]}")); | ||||||
|   JsonObject obj = doc.as<JsonObject>(); |   JsonObject obj = doc.as<JsonObject>(); | ||||||
| @@ -29,12 +28,12 @@ void setup() { | |||||||
|  |  | ||||||
|   // You can use a Flash String to set an element of a JsonObject |   // You can use a Flash String to set an element of a JsonObject | ||||||
|   // WARNING: the content of the Flash String will be duplicated in the |   // WARNING: the content of the Flash String will be duplicated in the | ||||||
|   // JsonBuffer. |   // JsonDocument. | ||||||
|   obj[F("time")] = time; |   obj[F("time")] = time; | ||||||
|  |  | ||||||
|   // You can set a Flash String to a JsonObject or JsonArray: |   // You can set a Flash String to a JsonObject or JsonArray: | ||||||
|   // WARNING: the content of the Flash String will be duplicated in the |   // WARNING: the content of the Flash String will be duplicated in the | ||||||
|   // JsonBuffer. |   // JsonDocument. | ||||||
|   obj["sensor"] = F("gps"); |   obj["sensor"] = F("gps"); | ||||||
|  |  | ||||||
|   // It works with serialized() too: |   // It works with serialized() too: | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| // This example shows the different ways you can use String with ArduinoJson. | // This example shows the different ways you can use String with ArduinoJson. | ||||||
| // | // | ||||||
| // Use String objects sparingly, because ArduinoJson duplicates them in the | // Use String objects sparingly, because ArduinoJson duplicates them in the | ||||||
| // JsonBuffer. Prefer plain old char[], as they are more efficient in term of | // JsonDocument. Prefer plain old char[], as they are more efficient in term of | ||||||
| // code size, speed, and memory usage. | // code size, speed, and memory usage. | ||||||
|  |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
| @@ -14,7 +14,7 @@ void setup() { | |||||||
|   DynamicJsonDocument doc(1024); |   DynamicJsonDocument doc(1024); | ||||||
|  |  | ||||||
|   // You can use a String as your JSON input. |   // You can use a String as your JSON input. | ||||||
|   // WARNING: the content of the String will be duplicated in the JsonBuffer. |   // WARNING: the string in the input  will be duplicated in the JsonDocument. | ||||||
|   String input = |   String input = | ||||||
|       "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; |       "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; | ||||||
|   deserializeJson(doc, input); |   deserializeJson(doc, input); | ||||||
| @@ -25,11 +25,11 @@ void setup() { | |||||||
|   long time = obj[String("time")]; |   long time = obj[String("time")]; | ||||||
|  |  | ||||||
|   // You can use a String to set an element of a JsonObject |   // You can use a String to set an element of a JsonObject | ||||||
|   // WARNING: the content of the String will be duplicated in the JsonBuffer. |   // WARNING: the content of the String will be duplicated in the JsonDocument. | ||||||
|   obj[String("time")] = time; |   obj[String("time")] = time; | ||||||
|  |  | ||||||
|   // You can get a String from a JsonObject or JsonArray: |   // You can get a String from a JsonObject or JsonArray: | ||||||
|   // No duplication is done, at least not in the JsonBuffer. |   // No duplication is done, at least not in the JsonDocument. | ||||||
|   String sensor = obj["sensor"]; |   String sensor = obj["sensor"]; | ||||||
|  |  | ||||||
|   // Unfortunately, the following doesn't work (issue #118): |   // Unfortunately, the following doesn't work (issue #118): | ||||||
| @@ -38,14 +38,14 @@ void setup() { | |||||||
|   sensor = obj["sensor"].as<String>(); |   sensor = obj["sensor"].as<String>(); | ||||||
|  |  | ||||||
|   // You can set a String to a JsonObject or JsonArray: |   // You can set a String to a JsonObject or JsonArray: | ||||||
|   // WARNING: the content of the String will be duplicated in the JsonBuffer. |   // WARNING: the content of the String will be duplicated in the JsonDocument. | ||||||
|   obj["sensor"] = sensor; |   obj["sensor"] = sensor; | ||||||
|  |  | ||||||
|   // It works with serialized() too: |   // It works with serialized() too: | ||||||
|   obj["sensor"] = serialized(sensor); |   obj["sensor"] = serialized(sensor); | ||||||
|  |  | ||||||
|   // You can also concatenate strings |   // You can also concatenate strings | ||||||
|   // WARNING: the content of the String will be duplicated in the JsonBuffer. |   // WARNING: the content of the String will be duplicated in the JsonDocument. | ||||||
|   obj[String("sen") + "sor"] = String("gp") + "s"; |   obj[String("sen") + "sor"] = String("gp") + "s"; | ||||||
|  |  | ||||||
|   // You can compare the content of a JsonObject with a String |   // You can compare the content of a JsonObject with a String | ||||||
|   | |||||||
| @@ -14,10 +14,10 @@ | |||||||
| #include "ArduinoJson/Document/StaticJsonDocument.hpp" | #include "ArduinoJson/Document/StaticJsonDocument.hpp" | ||||||
|  |  | ||||||
| #include "ArduinoJson/Array/ArrayImpl.hpp" | #include "ArduinoJson/Array/ArrayImpl.hpp" | ||||||
| #include "ArduinoJson/Array/ArraySubscript.hpp" | #include "ArduinoJson/Array/ElementProxy.hpp" | ||||||
| #include "ArduinoJson/Collection/CollectionImpl.hpp" | #include "ArduinoJson/Collection/CollectionImpl.hpp" | ||||||
|  | #include "ArduinoJson/Object/MemberProxy.hpp" | ||||||
| #include "ArduinoJson/Object/ObjectImpl.hpp" | #include "ArduinoJson/Object/ObjectImpl.hpp" | ||||||
| #include "ArduinoJson/Object/ObjectSubscript.hpp" |  | ||||||
| #include "ArduinoJson/Variant/VariantAsImpl.hpp" | #include "ArduinoJson/Variant/VariantAsImpl.hpp" | ||||||
| #include "ArduinoJson/Variant/VariantImpl.hpp" | #include "ArduinoJson/Variant/VariantImpl.hpp" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,11 +9,14 @@ | |||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| inline ArrayRef ArrayRef::createNestedArray() const { | template <typename TArray> | ||||||
|   return add().to<ArrayRef>(); | inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const { | ||||||
|  |   return impl()->add().template to<ArrayRef>(); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline ObjectRef ArrayRef::createNestedObject() const { | template <typename TArray> | ||||||
|   return add().to<ObjectRef>(); | inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const { | ||||||
|  |   return impl()->add().template to<ObjectRef>(); | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -16,11 +16,16 @@ | |||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| class ObjectRef; | class ObjectRef; | ||||||
| class ArraySubscript; | template <typename> | ||||||
|  | class ElementProxy; | ||||||
|  |  | ||||||
| template <typename TData> | template <typename TData> | ||||||
| class ArrayRefBase { | class ArrayRefBase { | ||||||
|  public: |  public: | ||||||
|  |   operator VariantConstRef() const { | ||||||
|  |     return VariantConstRef(reinterpret_cast<const VariantData*>(_data)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename Visitor> |   template <typename Visitor> | ||||||
|   FORCE_INLINE void accept(Visitor& visitor) const { |   FORCE_INLINE void accept(Visitor& visitor) const { | ||||||
|     arrayAccept(_data, visitor); |     arrayAccept(_data, visitor); | ||||||
| @@ -30,10 +35,6 @@ class ArrayRefBase { | |||||||
|     return _data == 0; |     return _data == 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE VariantConstRef operator[](size_t index) const { |  | ||||||
|     return VariantConstRef(_data ? _data->get(index) : 0); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE size_t memoryUsage() const { |   FORCE_INLINE size_t memoryUsage() const { | ||||||
|     return _data ? _data->memoryUsage() : 0; |     return _data ? _data->memoryUsage() : 0; | ||||||
|   } |   } | ||||||
| @@ -74,9 +75,15 @@ class ArrayConstRef : public ArrayRefBase<const CollectionData>, | |||||||
|   FORCE_INLINE bool operator==(ArrayConstRef rhs) const { |   FORCE_INLINE bool operator==(ArrayConstRef rhs) const { | ||||||
|     return arrayEquals(_data, rhs._data); |     return arrayEquals(_data, rhs._data); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   FORCE_INLINE VariantConstRef operator[](size_t index) const { | ||||||
|  |     return VariantConstRef(_data ? _data->get(index) : 0); | ||||||
|  |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable { | class ArrayRef : public ArrayRefBase<CollectionData>, | ||||||
|  |                  public ArrayShortcuts<ArrayRef>, | ||||||
|  |                  public Visitable { | ||||||
|   typedef ArrayRefBase<CollectionData> base_type; |   typedef ArrayRefBase<CollectionData> base_type; | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
| @@ -94,27 +101,7 @@ class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable { | |||||||
|     return ArrayConstRef(_data); |     return ArrayConstRef(_data); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Adds the specified value at the end of the array. |   using ArrayShortcuts::add; | ||||||
|   // |  | ||||||
|   // bool add(TValue); |  | ||||||
|   // TValue = bool, long, int, short, float, double, serialized, VariantRef, |  | ||||||
|   //          std::string, String, ObjectRef |  | ||||||
|   template <typename T> |  | ||||||
|   FORCE_INLINE bool add(const T& value) const { |  | ||||||
|     return add().set(value); |  | ||||||
|   } |  | ||||||
|   // Adds the specified value at the end of the array. |  | ||||||
|   FORCE_INLINE bool add(ArrayConstRef value) const { |  | ||||||
|     return add().set(value); |  | ||||||
|   } |  | ||||||
|   // |  | ||||||
|   // bool add(TValue); |  | ||||||
|   // TValue = char*, const char*, const __FlashStringHelper* |  | ||||||
|   template <typename T> |  | ||||||
|   FORCE_INLINE bool add(T* value) const { |  | ||||||
|     return add().set(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   VariantRef add() const { |   VariantRef add() const { | ||||||
|     return VariantRef(_pool, arrayAdd(_data, _pool)); |     return VariantRef(_pool, arrayAdd(_data, _pool)); | ||||||
|   } |   } | ||||||
| @@ -187,11 +174,6 @@ class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE ArrayRef createNestedArray() const; |  | ||||||
|   FORCE_INLINE ObjectRef createNestedObject() const; |  | ||||||
|  |  | ||||||
|   FORCE_INLINE ArraySubscript operator[](size_t index) const; |  | ||||||
|  |  | ||||||
|   FORCE_INLINE bool operator==(ArrayRef rhs) const { |   FORCE_INLINE bool operator==(ArrayRef rhs) const { | ||||||
|     return arrayEquals(_data, rhs._data); |     return arrayEquals(_data, rhs._data); | ||||||
|   } |   } | ||||||
|   | |||||||
							
								
								
									
										47
									
								
								src/ArduinoJson/Array/ArrayShortcuts.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/ArduinoJson/Array/ArrayShortcuts.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Polyfills/attributes.hpp" | ||||||
|  | #include "../Polyfills/type_traits.hpp" | ||||||
|  |  | ||||||
|  | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  | // Forward declarations. | ||||||
|  | template <typename> | ||||||
|  | class ElementProxy; | ||||||
|  |  | ||||||
|  | template <typename TArray> | ||||||
|  | class ArrayShortcuts { | ||||||
|  |  public: | ||||||
|  |   // Returns the element at specified index if the variant is an array. | ||||||
|  |   FORCE_INLINE ElementProxy<const TArray &> operator[](size_t index) const; | ||||||
|  |  | ||||||
|  |   FORCE_INLINE ObjectRef createNestedObject() const; | ||||||
|  |  | ||||||
|  |   FORCE_INLINE ArrayRef createNestedArray() const; | ||||||
|  |  | ||||||
|  |   // Adds the specified value at the end of the array. | ||||||
|  |   // | ||||||
|  |   // bool add(TValue); | ||||||
|  |   // TValue = bool, long, int, short, float, double, serialized, VariantRef, | ||||||
|  |   //          std::string, String, ObjectRef | ||||||
|  |   template <typename T> | ||||||
|  |   FORCE_INLINE bool add(const T &value) const { | ||||||
|  |     return impl()->add().set(value); | ||||||
|  |   } | ||||||
|  |   // | ||||||
|  |   // bool add(TValue); | ||||||
|  |   // TValue = char*, const char*, const __FlashStringHelper* | ||||||
|  |   template <typename T> | ||||||
|  |   FORCE_INLINE bool add(T *value) const { | ||||||
|  |     return impl()->add().set(value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   const TArray *impl() const { | ||||||
|  |     return static_cast<const TArray *>(this); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
| @@ -13,14 +13,18 @@ | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| class ArraySubscript : public VariantOperators<ArraySubscript>, | 
 | ||||||
|  | template <typename TArray> | ||||||
|  | class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | ||||||
|                      public Visitable { |                      public Visitable { | ||||||
|  |   typedef ElementProxy<TArray> this_type; | ||||||
|  | 
 | ||||||
|  public: |  public: | ||||||
|   FORCE_INLINE ArraySubscript(ArrayRef array, size_t index) |   FORCE_INLINE ElementProxy(TArray array, size_t index) | ||||||
|       : _array(array), _index(index) {} |       : _array(array), _index(index) {} | ||||||
| 
 | 
 | ||||||
|   FORCE_INLINE ArraySubscript& operator=(const ArraySubscript& src) { |   FORCE_INLINE this_type& operator=(const this_type& src) { | ||||||
|     get_impl().set(src.as<VariantConstRef>()); |     getElement().set(src.as<VariantConstRef>()); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @@ -30,36 +34,36 @@ class ArraySubscript : public VariantOperators<ArraySubscript>, | |||||||
|   // TValue = bool, long, int, short, float, double, serialized, VariantRef,
 |   // TValue = bool, long, int, short, float, double, serialized, VariantRef,
 | ||||||
|   //          std::string, String, ArrayRef, ObjectRef
 |   //          std::string, String, ArrayRef, ObjectRef
 | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE ArraySubscript& operator=(const T& src) { |   FORCE_INLINE this_type& operator=(const T& src) { | ||||||
|     get_impl().set(src); |     getElement().set(src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|   //
 |   //
 | ||||||
|   // operator=(TValue)
 |   // operator=(TValue)
 | ||||||
|   // TValue = char*, const char*, const __FlashStringHelper*
 |   // TValue = char*, const char*, const __FlashStringHelper*
 | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE ArraySubscript& operator=(T* src) { |   FORCE_INLINE this_type& operator=(T* src) { | ||||||
|     get_impl().set(src); |     getElement().set(src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   FORCE_INLINE bool isNull() const { |   FORCE_INLINE bool isNull() const { | ||||||
|     return get_impl().isNull(); |     return getElement().isNull(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE typename VariantAs<T>::type as() const { |   FORCE_INLINE typename VariantAs<T>::type as() const { | ||||||
|     return get_impl().as<T>(); |     return getElement().template as<T>(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool is() const { |   FORCE_INLINE bool is() const { | ||||||
|     return get_impl().is<T>(); |     return getElement().template is<T>(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE typename VariantTo<T>::type to() const { |   FORCE_INLINE typename VariantTo<T>::type to() const { | ||||||
|     return get_impl().to<T>(); |     return getElement().template to<T>(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Replaces the value
 |   // Replaces the value
 | ||||||
| @@ -69,42 +73,65 @@ class ArraySubscript : public VariantOperators<ArraySubscript>, | |||||||
|   //          std::string, String, ArrayRef, ObjectRef
 |   //          std::string, String, ArrayRef, ObjectRef
 | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(const TValue& value) const { |   FORCE_INLINE bool set(const TValue& value) const { | ||||||
|     return get_impl().set(value); |     return getElement().set(value); | ||||||
|   } |   } | ||||||
|   //
 |   //
 | ||||||
|   // bool set(TValue)
 |   // bool set(TValue)
 | ||||||
|   // TValue = char*, const char*, const __FlashStringHelper*
 |   // TValue = char*, const char*, const __FlashStringHelper*
 | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(TValue* value) const { |   FORCE_INLINE bool set(TValue* value) const { | ||||||
|     return get_impl().set(value); |     return getElement().set(value); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   template <typename Visitor> |   template <typename Visitor> | ||||||
|   void accept(Visitor& visitor) const { |   void accept(Visitor& visitor) const { | ||||||
|     return get_impl().accept(visitor); |     return getElement().accept(visitor); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   FORCE_INLINE size_t size() const { |   FORCE_INLINE size_t size() const { | ||||||
|     return get_impl().size(); |     return getElement().size(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   template <typename TNestedKey> | ||||||
|  |   VariantRef get(TNestedKey* key) const { | ||||||
|  |     return getElement().get(key); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   template <typename TNestedKey> | ||||||
|  |   VariantRef get(const TNestedKey& key) const { | ||||||
|  |     return getElement().get(key); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   template <typename TNestedKey> | ||||||
|  |   VariantRef getOrCreate(TNestedKey* key) const { | ||||||
|  |     return getElement().getOrCreate(key); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   template <typename TNestedKey> | ||||||
|  |   VariantRef getOrCreate(const TNestedKey& key) const { | ||||||
|  |     return getElement().getOrCreate(key); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   using ArrayShortcuts<ElementProxy>::add; | ||||||
|  |   VariantRef add() const { | ||||||
|  |     return getElement().add(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  private: |  private: | ||||||
|   FORCE_INLINE VariantRef get_impl() const { |   FORCE_INLINE VariantRef getElement() const { | ||||||
|     return _array.get(_index); |     return _array.get(_index); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   ArrayRef _array; |   TArray _array; | ||||||
|   const size_t _index; |   const size_t _index; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename TImpl> | template <typename TArray> | ||||||
| inline ArraySubscript VariantSubscripts<TImpl>::operator[](size_t index) const { | inline ElementProxy<const TArray&> ArrayShortcuts<TArray>::operator[]( | ||||||
|   return impl()->template as<ArrayRef>()[index]; |     size_t index) const { | ||||||
|  |   return ElementProxy<const TArray&>(*impl(), index); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline ArraySubscript ArrayRef::operator[](size_t index) const { |  | ||||||
|   return ArraySubscript(*this, index); |  | ||||||
| } |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE
 | }  // namespace ARDUINOJSON_NAMESPACE
 | ||||||
| 
 | 
 | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| @@ -9,7 +9,8 @@ | |||||||
| #include "../Variant/VariantRef.hpp" | #include "../Variant/VariantRef.hpp" | ||||||
| #include "../Variant/VariantTo.hpp" | #include "../Variant/VariantTo.hpp" | ||||||
|  |  | ||||||
| #include "../Array/ArraySubscript.hpp" | #include "../Array/ElementProxy.hpp" | ||||||
|  | #include "../Object/MemberProxy.hpp" | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| @@ -81,22 +82,51 @@ class JsonDocument : public Visitable { | |||||||
|     return _data; |     return _data; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // ObjectSubscript operator[](TKey) |   ArrayRef createNestedArray() { | ||||||
|   // TKey = const std::string&, const String& |     return add().to<ArrayRef>(); | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey>::value, |  | ||||||
|                                   ObjectSubscript<const TKey&> >::type |  | ||||||
|   operator[](const TKey& key) { |  | ||||||
|     return getVariant()[key]; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // ObjectSubscript operator[](TKey); |   template <typename TKey> | ||||||
|   // TKey = const char*, const char[N], const __FlashStringHelper* |   ArrayRef createNestedArray(TKey* key) { | ||||||
|  |     return getOrCreate(key).template to<ArrayRef>(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   ArrayRef createNestedArray(const TKey& key) { | ||||||
|  |     return getOrCreate(key).template to<ArrayRef>(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ObjectRef createNestedObject() { | ||||||
|  |     return add().to<ObjectRef>(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   ObjectRef createNestedObject(TKey* key) { | ||||||
|  |     return getOrCreate(key).template to<ObjectRef>(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   ObjectRef createNestedObject(const TKey& key) { | ||||||
|  |     return getOrCreate(key).template to<ObjectRef>(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // MemberProxy operator[](TKey) | ||||||
|  |   // TKey = const std::string&, const String& | ||||||
|   template <typename TKey> |   template <typename TKey> | ||||||
|   FORCE_INLINE |   FORCE_INLINE | ||||||
|       typename enable_if<IsString<TKey*>::value, ObjectSubscript<TKey*> >::type |       typename enable_if<IsString<TKey>::value, | ||||||
|  |                          MemberProxy<JsonDocument&, const TKey&> >::type | ||||||
|  |       operator[](const TKey& key) { | ||||||
|  |     return MemberProxy<JsonDocument&, const TKey&>(*this, key); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // MemberProxy operator[](TKey); | ||||||
|  |   // TKey = const char*, const char[N], const __FlashStringHelper* | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE typename enable_if<IsString<TKey*>::value, | ||||||
|  |                                   MemberProxy<JsonDocument&, TKey*> >::type | ||||||
|   operator[](TKey* key) { |   operator[](TKey* key) { | ||||||
|     return getVariant()[key]; |     return MemberProxy<JsonDocument&, TKey*>(*this, key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // VariantConstRef operator[](TKey) const |   // VariantConstRef operator[](TKey) const | ||||||
| @@ -115,12 +145,56 @@ class JsonDocument : public Visitable { | |||||||
|     return getVariant()[key]; |     return getVariant()[key]; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE ArraySubscript operator[](size_t index) { |   FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) { | ||||||
|     return getVariant()[index]; |     return ElementProxy<JsonDocument&>(*this, index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE VariantConstRef operator[](size_t index) const { |   FORCE_INLINE VariantConstRef operator[](size_t index) const { | ||||||
|     return getVariant()[index]; |     return VariantConstRef(_data.get(index)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   FORCE_INLINE VariantRef get(size_t index) { | ||||||
|  |     return VariantRef(&_pool, _data.get(index)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE VariantRef get(TKey* key) { | ||||||
|  |     return VariantRef(&_pool, _data.get(wrapString(key))); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantRef>::type get( | ||||||
|  |       const TKey& key) { | ||||||
|  |     return VariantRef(&_pool, _data.get(wrapString(key))); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(TKey* key) { | ||||||
|  |     return VariantRef(&_pool, _data.getOrCreate(wrapString(key), &_pool)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(const TKey& key) { | ||||||
|  |     return VariantRef(&_pool, _data.getOrCreate(wrapString(key), &_pool)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   FORCE_INLINE VariantRef add() { | ||||||
|  |     return VariantRef(&_pool, _data.add(&_pool)); | ||||||
|  |   } | ||||||
|  |   // | ||||||
|  |   // bool add(TValue); | ||||||
|  |   // TValue = bool, long, int, short, float, double, serialized, VariantRef, | ||||||
|  |   //          std::string, String, ObjectRef | ||||||
|  |   template <typename T> | ||||||
|  |   FORCE_INLINE bool add(const T& value) { | ||||||
|  |     return add().set(value); | ||||||
|  |   } | ||||||
|  |   // | ||||||
|  |   // bool add(TValue); | ||||||
|  |   // TValue = char*, const char*, const __FlashStringHelper* | ||||||
|  |   template <typename T> | ||||||
|  |   FORCE_INLINE bool add(T* value) { | ||||||
|  |     return add().set(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   | |||||||
| @@ -15,4 +15,7 @@ struct Visitable { | |||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| struct IsVisitable : is_base_of<Visitable, T> {}; | struct IsVisitable : is_base_of<Visitable, T> {}; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct IsVisitable<T&> : IsVisitable<T> {}; | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -15,21 +15,21 @@ | |||||||
| 
 | 
 | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| 
 | 
 | ||||||
| template <typename TStringRef> | template <typename TObject, typename TString> | ||||||
| class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >, | class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >, | ||||||
|                     public Visitable { |                     public Visitable { | ||||||
|   typedef ObjectSubscript<TStringRef> this_type; |   typedef MemberProxy<TObject, TString> this_type; | ||||||
| 
 | 
 | ||||||
|  public: |  public: | ||||||
|   FORCE_INLINE ObjectSubscript(ObjectRef object, TStringRef key) |   FORCE_INLINE MemberProxy(TObject variant, TString key) | ||||||
|       : _object(object), _key(key) {} |       : _object(variant), _key(key) {} | ||||||
| 
 | 
 | ||||||
|   operator VariantConstRef() const { |   FORCE_INLINE operator VariantConstRef() const { | ||||||
|     return get_impl(); |     return getMember(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   FORCE_INLINE this_type &operator=(const this_type &src) { |   FORCE_INLINE this_type &operator=(const this_type &src) { | ||||||
|     set_impl().set(src); |     getOrCreateMember().set(src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @@ -41,7 +41,7 @@ class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >, | |||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type |   FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type | ||||||
|   operator=(const TValue &src) { |   operator=(const TValue &src) { | ||||||
|     set_impl().set(src); |     getOrCreateMember().set(src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|   //
 |   //
 | ||||||
| @@ -49,27 +49,27 @@ class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >, | |||||||
|   // TValue = char*, const char*, const __FlashStringHelper*
 |   // TValue = char*, const char*, const __FlashStringHelper*
 | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE this_type &operator=(TValue *src) { |   FORCE_INLINE this_type &operator=(TValue *src) { | ||||||
|     set_impl().set(src); |     getOrCreateMember().set(src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   FORCE_INLINE bool isNull() const { |   FORCE_INLINE bool isNull() const { | ||||||
|     return get_impl().isNull(); |     return getMember().isNull(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE typename VariantAs<TValue>::type as() const { |   FORCE_INLINE typename VariantAs<TValue>::type as() const { | ||||||
|     return get_impl().template as<TValue>(); |     return getMember().template as<TValue>(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool is() const { |   FORCE_INLINE bool is() const { | ||||||
|     return get_impl().template is<TValue>(); |     return getMember().template is<TValue>(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE typename VariantTo<TValue>::type to() { |   FORCE_INLINE typename VariantTo<TValue>::type to() { | ||||||
|     return set_impl().template to<TValue>(); |     return getOrCreateMember().template to<TValue>(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Sets the specified value.
 |   // Sets the specified value.
 | ||||||
| @@ -81,48 +81,73 @@ class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >, | |||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set( |   FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set( | ||||||
|       const TValue &value) { |       const TValue &value) { | ||||||
|     return set_impl().set(value); |     return getOrCreateMember().set(value); | ||||||
|   } |   } | ||||||
|   //
 |   //
 | ||||||
|   // bool set(TValue);
 |   // bool set(TValue);
 | ||||||
|   // TValue = char*, const char, const __FlashStringHelper*
 |   // TValue = char*, const char, const __FlashStringHelper*
 | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(const TValue *value) { |   FORCE_INLINE bool set(const TValue *value) { | ||||||
|     return set_impl().set(value); |     return getOrCreateMember().set(value); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   template <typename Visitor> |   template <typename Visitor> | ||||||
|   void accept(Visitor &visitor) const { |   void accept(Visitor &visitor) const { | ||||||
|     return get_impl().accept(visitor); |     return getMember().accept(visitor); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   using ArrayShortcuts<MemberProxy>::add; | ||||||
|  |   FORCE_INLINE VariantRef add() const { | ||||||
|  |     return getOrCreateMember().add(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   template <typename TNestedKey> | ||||||
|  |   FORCE_INLINE VariantRef get(TNestedKey *key) const { | ||||||
|  |     return getMember().get(key); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   template <typename TNestedKey> | ||||||
|  |   FORCE_INLINE VariantRef get(const TNestedKey &key) const { | ||||||
|  |     return getMember().get(key); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   template <typename TNestedKey> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(TNestedKey *key) const { | ||||||
|  |     return getOrCreateMember().getOrCreate(key); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   template <typename TNestedKey> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(const TNestedKey &key) const { | ||||||
|  |     return getOrCreateMember().getOrCreate(key); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  private: |  private: | ||||||
|   FORCE_INLINE VariantRef get_impl() const { |   FORCE_INLINE VariantRef getMember() const { | ||||||
|     return _object.get(_key); |     return _object.get(_key); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   FORCE_INLINE VariantRef set_impl() const { |   FORCE_INLINE VariantRef getOrCreateMember() const { | ||||||
|     return _object.set(_key); |     return _object.getOrCreate(_key); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   ObjectRef _object; |   TObject _object; | ||||||
|   TStringRef _key; |   TString _key; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename TImpl> | template <typename TObject> | ||||||
| template <typename TString> | template <typename TString> | ||||||
| inline typename enable_if<IsString<TString>::value, | inline typename enable_if<IsString<TString>::value, | ||||||
|                           ObjectSubscript<const TString &> >::type |                           MemberProxy<const TObject &, const TString &> >::type | ||||||
|     VariantSubscripts<TImpl>::operator[](const TString &key) const { |     ObjectShortcuts<TObject>::operator[](const TString &key) const { | ||||||
|   return impl()->template as<ObjectRef>()[key]; |   return MemberProxy<const TObject &, const TString &>(*impl(), key); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename TImpl> | template <typename TObject> | ||||||
| template <typename TString> | template <typename TString> | ||||||
| inline typename enable_if<IsString<TString *>::value, | inline typename enable_if<IsString<TString *>::value, | ||||||
|                           ObjectSubscript<TString *> >::type |                           MemberProxy<const TObject &, TString *> >::type | ||||||
|     VariantSubscripts<TImpl>::operator[](TString *key) const { |     ObjectShortcuts<TObject>::operator[](TString *key) const { | ||||||
|   return impl()->template as<ObjectRef>()[key]; |   return MemberProxy<const TObject &, TString *>(*impl(), key); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE
 | }  // namespace ARDUINOJSON_NAMESPACE
 | ||||||
| @@ -40,7 +40,8 @@ void objectRemove(CollectionData *obj, TKey key) { | |||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TKey> | ||||||
| inline VariantData *objectSet(CollectionData *obj, TKey key, MemoryPool *pool) { | inline VariantData *objectGetOrCreate(CollectionData *obj, TKey key, | ||||||
|  |                                       MemoryPool *pool) { | ||||||
|   if (!obj) return 0; |   if (!obj) return 0; | ||||||
|  |  | ||||||
|   // ignore null key |   // ignore null key | ||||||
|   | |||||||
| @@ -9,13 +9,31 @@ | |||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
|  | template <typename TObject> | ||||||
| template <typename TString> | template <typename TString> | ||||||
| inline ArrayRef ObjectRef::createNestedArray(const TString& key) const { | inline ArrayRef ObjectShortcuts<TObject>::createNestedArray( | ||||||
|   return set(key).template to<ArrayRef>(); |     const TString& key) const { | ||||||
|  |   return impl()->getOrCreate(key).template to<ArrayRef>(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <typename TObject> | ||||||
| template <typename TString> | template <typename TString> | ||||||
| inline ArrayRef ObjectRef::createNestedArray(TString* key) const { | inline ArrayRef ObjectShortcuts<TObject>::createNestedArray( | ||||||
|   return set(key).template to<ArrayRef>(); |     TString* key) const { | ||||||
|  |   return impl()->getOrCreate(key).template to<ArrayRef>(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TObject> | ||||||
|  | template <typename TKey> | ||||||
|  | ObjectRef ObjectShortcuts<TObject>::createNestedObject(const TKey& key) const { | ||||||
|  |   return impl()->getOrCreate(key).template to<ObjectRef>(); | ||||||
|  | } | ||||||
|  | // | ||||||
|  | // ObjectRef createNestedObject(TKey); | ||||||
|  | // TKey = char*, const char*, char[], const char[], const __FlashStringHelper* | ||||||
|  | template <typename TObject> | ||||||
|  | template <typename TKey> | ||||||
|  | ObjectRef ObjectShortcuts<TObject>::createNestedObject(TKey* key) const { | ||||||
|  |   return impl()->getOrCreate(key).template to<ObjectRef>(); | ||||||
| } | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -17,6 +17,10 @@ namespace ARDUINOJSON_NAMESPACE { | |||||||
| template <typename TData> | template <typename TData> | ||||||
| class ObjectRefBase { | class ObjectRefBase { | ||||||
|  public: |  public: | ||||||
|  |   operator VariantConstRef() const { | ||||||
|  |     return VariantConstRef(reinterpret_cast<const VariantData*>(_data)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename Visitor> |   template <typename Visitor> | ||||||
|   FORCE_INLINE void accept(Visitor& visitor) const { |   FORCE_INLINE void accept(Visitor& visitor) const { | ||||||
|     objectAccept(_data, visitor); |     objectAccept(_data, visitor); | ||||||
| @@ -127,7 +131,9 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>, | |||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable { | class ObjectRef : public ObjectRefBase<CollectionData>, | ||||||
|  |                   public ObjectShortcuts<ObjectRef>, | ||||||
|  |                   public Visitable { | ||||||
|   typedef ObjectRefBase<CollectionData> base_type; |   typedef ObjectRefBase<CollectionData> base_type; | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
| @@ -164,68 +170,30 @@ class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable { | |||||||
|     return _data->copyFrom(*src._data, _pool); |     return _data->copyFrom(*src._data, _pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Creates and adds a ArrayRef. |  | ||||||
|   // |  | ||||||
|   // ArrayRef createNestedArray(TKey); |  | ||||||
|   // TKey = const std::string&, const String& |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE ArrayRef createNestedArray(const TKey& key) const; |  | ||||||
|   // ArrayRef createNestedArray(TKey); |  | ||||||
|   // TKey = char*, const char*, char[], const char[], const __FlashStringHelper* |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE ArrayRef createNestedArray(TKey* key) const; |  | ||||||
|  |  | ||||||
|   // Creates and adds a ObjectRef. |  | ||||||
|   // |  | ||||||
|   // ObjectRef createNestedObject(TKey); |  | ||||||
|   // TKey = const std::string&, const String& |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE ObjectRef createNestedObject(const TKey& key) const { |  | ||||||
|     return set(key).template to<ObjectRef>(); |  | ||||||
|   } |  | ||||||
|   // |  | ||||||
|   // ObjectRef createNestedObject(TKey); |  | ||||||
|   // TKey = char*, const char*, char[], const char[], const __FlashStringHelper* |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE ObjectRef createNestedObject(TKey* key) const { |  | ||||||
|     return set(key).template to<ObjectRef>(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // Gets the value associated with the specified key. | ||||||
|   // |   // | ||||||
|   // TValue get<TValue>(TKey) const; |   // VariantRef get<TValue>(TKey) const; | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   // TValue = bool, char, long, int, short, float, double, |  | ||||||
|   //          std::string, String, ArrayRef, ObjectRef |  | ||||||
|   template <typename TKey> |   template <typename TKey> | ||||||
|   FORCE_INLINE VariantRef get(const TKey& key) const { |   FORCE_INLINE VariantRef get(const TKey& key) const { | ||||||
|     return get_impl(wrapString(key)); |     return get_impl(wrapString(key)); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // TValue get<TValue>(TKey) const; |   // VariantRef get<TValue>(TKey) const; | ||||||
|   // TKey = char*, const char*, const __FlashStringHelper* |   // TKey = char*, const char*, const __FlashStringHelper* | ||||||
|   // TValue = bool, char, long, int, short, float, double, |  | ||||||
|   //          std::string, String, ArrayRef, ObjectRef |  | ||||||
|   template <typename TKey> |   template <typename TKey> | ||||||
|   FORCE_INLINE VariantRef get(TKey* key) const { |   FORCE_INLINE VariantRef get(TKey* key) const { | ||||||
|     return get_impl(wrapString(key)); |     return get_impl(wrapString(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets or sets the value associated with the specified key. |  | ||||||
|   // |  | ||||||
|   // ObjectSubscript operator[](TKey) |  | ||||||
|   // TKey = const std::string&, const String& |  | ||||||
|   template <typename TKey> |   template <typename TKey> | ||||||
|   FORCE_INLINE ObjectSubscript<const TKey&> operator[](const TKey& key) const { |   FORCE_INLINE VariantRef getOrCreate(TKey* key) const { | ||||||
|     return ObjectSubscript<const TKey&>(*this, key); |     return getOrCreate_impl(wrapString(key)); | ||||||
|   } |   } | ||||||
|   // |  | ||||||
|   // ObjectSubscript operator[](TKey) |  | ||||||
|   // TKey = char*, const char*, char[], const char[N], const |  | ||||||
|   // __FlashStringHelper* |  | ||||||
|   template <typename TKey> |   template <typename TKey> | ||||||
|   FORCE_INLINE ObjectSubscript<TKey*> operator[](TKey* key) const { |   FORCE_INLINE VariantRef getOrCreate(const TKey& key) const { | ||||||
|     return ObjectSubscript<TKey*>(*this, key); |     return getOrCreate_impl(wrapString(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE bool operator==(ObjectRef rhs) const { |   FORCE_INLINE bool operator==(ObjectRef rhs) const { | ||||||
| @@ -253,16 +221,6 @@ class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable { | |||||||
|     objectRemove(_data, wrapString(key)); |     objectRemove(_data, wrapString(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE VariantRef set(TKey* key) const { |  | ||||||
|     return set_impl(wrapString(key)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE VariantRef set(const TKey& key) const { |  | ||||||
|     return set_impl(wrapString(key)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   template <typename TKey> |   template <typename TKey> | ||||||
|   FORCE_INLINE VariantRef get_impl(TKey key) const { |   FORCE_INLINE VariantRef get_impl(TKey key) const { | ||||||
| @@ -270,8 +228,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   template <typename TKey> | ||||||
|   FORCE_INLINE VariantRef set_impl(TKey key) const { |   FORCE_INLINE VariantRef getOrCreate_impl(TKey key) const { | ||||||
|     return VariantRef(_pool, objectSet(_data, key, _pool)); |     return VariantRef(_pool, objectGetOrCreate(_data, key, _pool)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   MemoryPool* _pool; |   MemoryPool* _pool; | ||||||
|   | |||||||
							
								
								
									
										61
									
								
								src/ArduinoJson/Object/ObjectShortcuts.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/ArduinoJson/Object/ObjectShortcuts.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Polyfills/attributes.hpp" | ||||||
|  | #include "../Polyfills/type_traits.hpp" | ||||||
|  | #include "../Strings/StringWrappers.hpp" | ||||||
|  |  | ||||||
|  | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  | template <typename TParent, typename TKey> | ||||||
|  | class MemberProxy; | ||||||
|  |  | ||||||
|  | template <typename TObject> | ||||||
|  | class ObjectShortcuts { | ||||||
|  |  public: | ||||||
|  |   // MemberProxy operator[](TKey) const; | ||||||
|  |   // TKey = const std::string&, const String& | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE | ||||||
|  |       typename enable_if<IsString<TKey>::value, | ||||||
|  |                          MemberProxy<const TObject &, const TKey &> >::type | ||||||
|  |       operator[](const TKey &key) const; | ||||||
|  |   // | ||||||
|  |   // MemberProxy operator[](TKey) const; | ||||||
|  |   // TKey = const char*, const char[N], const __FlashStringHelper* | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE typename enable_if<IsString<TKey *>::value, | ||||||
|  |                                   MemberProxy<const TObject &, TKey *> >::type | ||||||
|  |   operator[](TKey *key) const; | ||||||
|  |  | ||||||
|  |   // Creates and adds a ArrayRef. | ||||||
|  |   // | ||||||
|  |   // ArrayRef createNestedArray(TKey); | ||||||
|  |   // TKey = const std::string&, const String& | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE ArrayRef createNestedArray(const TKey &key) const; | ||||||
|  |   // ArrayRef createNestedArray(TKey); | ||||||
|  |   // TKey = char*, const char*, char[], const char[], const __FlashStringHelper* | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE ArrayRef createNestedArray(TKey *key) const; | ||||||
|  |  | ||||||
|  |   // Creates and adds a ObjectRef. | ||||||
|  |   // | ||||||
|  |   // ObjectRef createNestedObject(TKey); | ||||||
|  |   // TKey = const std::string&, const String& | ||||||
|  |   template <typename TKey> | ||||||
|  |   ObjectRef createNestedObject(const TKey &key) const; | ||||||
|  |   // | ||||||
|  |   // ObjectRef createNestedObject(TKey); | ||||||
|  |   // TKey = char*, const char*, char[], const char[], const __FlashStringHelper* | ||||||
|  |   template <typename TKey> | ||||||
|  |   ObjectRef createNestedObject(TKey *key) const; | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   const TObject *impl() const { | ||||||
|  |     return static_cast<const TObject *>(this); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
| @@ -7,7 +7,7 @@ | |||||||
| #include "VariantCasts.hpp" | #include "VariantCasts.hpp" | ||||||
| #include "VariantComparisons.hpp" | #include "VariantComparisons.hpp" | ||||||
| #include "VariantOr.hpp" | #include "VariantOr.hpp" | ||||||
| #include "VariantSubscripts.hpp" | #include "VariantShortcuts.hpp" | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| @@ -15,5 +15,5 @@ template <typename TImpl> | |||||||
| class VariantOperators : public VariantCasts<TImpl>, | class VariantOperators : public VariantCasts<TImpl>, | ||||||
|                          public VariantComparisons<TImpl>, |                          public VariantComparisons<TImpl>, | ||||||
|                          public VariantOr<TImpl>, |                          public VariantOr<TImpl>, | ||||||
|                          public VariantSubscripts<TImpl> {}; |                          public VariantShortcuts<TImpl> {}; | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								src/ArduinoJson/Operators/VariantShortcuts.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/ArduinoJson/Operators/VariantShortcuts.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Array/ArrayShortcuts.hpp" | ||||||
|  | #include "../Object/ObjectShortcuts.hpp" | ||||||
|  |  | ||||||
|  | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
|  | template <typename TVariant> | ||||||
|  | class VariantShortcuts : public ObjectShortcuts<TVariant>, | ||||||
|  |                          public ArrayShortcuts<TVariant> { | ||||||
|  |  public: | ||||||
|  |   using ArrayShortcuts<TVariant>::createNestedArray; | ||||||
|  |   using ArrayShortcuts<TVariant>::createNestedObject; | ||||||
|  |   using ArrayShortcuts<TVariant>::operator[]; | ||||||
|  |   using ObjectShortcuts<TVariant>::createNestedArray; | ||||||
|  |   using ObjectShortcuts<TVariant>::createNestedObject; | ||||||
|  |   using ObjectShortcuts<TVariant>::operator[]; | ||||||
|  | }; | ||||||
|  | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
| @@ -1,51 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include "../Polyfills/attributes.hpp" |  | ||||||
| #include "../Polyfills/type_traits.hpp" |  | ||||||
| #include "../Strings/StringWrappers.hpp" |  | ||||||
| #include "../Variant/VariantAs.hpp" |  | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { |  | ||||||
| class ArrayRef; |  | ||||||
| class ObjectRef; |  | ||||||
|  |  | ||||||
| // Forward declarations. |  | ||||||
| class ArraySubscript; |  | ||||||
| template <typename TKey> |  | ||||||
| class ObjectSubscript; |  | ||||||
|  |  | ||||||
| template <typename TImpl> |  | ||||||
| class VariantSubscripts { |  | ||||||
|  public: |  | ||||||
|   // Mimics an array. |  | ||||||
|   // Returns the element at specified index if the variant is an array. |  | ||||||
|   FORCE_INLINE ArraySubscript operator[](size_t index) const; |  | ||||||
|  |  | ||||||
|   // Mimics an object. |  | ||||||
|   // Returns the value associated with the specified key if the variant is |  | ||||||
|   // an object. |  | ||||||
|   // |  | ||||||
|   // ObjectSubscript operator[](TKey) const; |  | ||||||
|   // TKey = const std::string&, const String& |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey>::value, |  | ||||||
|                                   ObjectSubscript<const TKey &> >::type |  | ||||||
|   operator[](const TKey &key) const; |  | ||||||
|   // |  | ||||||
|   // ObjectSubscript operator[](TKey) const; |  | ||||||
|   // TKey = const char*, const char[N], const __FlashStringHelper* |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey *>::value, |  | ||||||
|                                   ObjectSubscript<TKey *> >::type |  | ||||||
|   operator[](TKey *key) const; |  | ||||||
|  |  | ||||||
|  private: |  | ||||||
|   const TImpl *impl() const { |  | ||||||
|     return static_cast<const TImpl *>(this); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE |  | ||||||
| @@ -12,19 +12,24 @@ | |||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
|  | // | ||||||
| enum { | enum { | ||||||
|   VALUE_IS_NULL = 0, |  | ||||||
|   VALUE_IS_LINKED_RAW, |  | ||||||
|   VALUE_IS_OWNED_RAW, |  | ||||||
|   VALUE_IS_LINKED_STRING, |  | ||||||
|   VALUE_IS_OWNED_STRING, |  | ||||||
|   VALUE_IS_BOOLEAN, |  | ||||||
|   VALUE_IS_POSITIVE_INTEGER, |  | ||||||
|   VALUE_IS_NEGATIVE_INTEGER, |  | ||||||
|   VALUE_IS_ARRAY, |  | ||||||
|   VALUE_IS_OBJECT, |  | ||||||
|   VALUE_IS_FLOAT, |  | ||||||
|   VALUE_MASK = 0x7F, |   VALUE_MASK = 0x7F, | ||||||
|  |  | ||||||
|  |   VALUE_IS_NULL = 0, | ||||||
|  |   VALUE_IS_LINKED_RAW = 0x01, | ||||||
|  |   VALUE_IS_OWNED_RAW = 0x02, | ||||||
|  |   VALUE_IS_LINKED_STRING = 0x03, | ||||||
|  |   VALUE_IS_OWNED_STRING = 0x04, | ||||||
|  |   VALUE_IS_BOOLEAN = 0x05, | ||||||
|  |   VALUE_IS_POSITIVE_INTEGER = 0x06, | ||||||
|  |   VALUE_IS_NEGATIVE_INTEGER = 0x07, | ||||||
|  |   VALUE_IS_FLOAT = 0x08, | ||||||
|  |  | ||||||
|  |   COLLECTION_MASK = 0x60, | ||||||
|  |   VALUE_IS_OBJECT = 0x20, | ||||||
|  |   VALUE_IS_ARRAY = 0x40, | ||||||
|  |  | ||||||
|   KEY_IS_OWNED = 0x80 |   KEY_IS_OWNED = 0x80 | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -67,7 +67,7 @@ class VariantData { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   CollectionData *asArray() { |   CollectionData *asArray() { | ||||||
|     return type() == VALUE_IS_ARRAY ? &_content.asCollection : 0; |     return isArray() ? &_content.asCollection : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   const CollectionData *asArray() const { |   const CollectionData *asArray() const { | ||||||
| @@ -75,7 +75,7 @@ class VariantData { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   CollectionData *asObject() { |   CollectionData *asObject() { | ||||||
|     return type() == VALUE_IS_OBJECT ? &_content.asCollection : 0; |     return isObject() ? &_content.asCollection : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   const CollectionData *asObject() const { |   const CollectionData *asObject() const { | ||||||
| @@ -135,13 +135,17 @@ class VariantData { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool isArray() const { |   bool isArray() const { | ||||||
|     return type() == VALUE_IS_ARRAY; |     return (_flags & VALUE_IS_ARRAY) != 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool isBoolean() const { |   bool isBoolean() const { | ||||||
|     return type() == VALUE_IS_BOOLEAN; |     return type() == VALUE_IS_BOOLEAN; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   bool isCollection() const { | ||||||
|  |     return (_flags & COLLECTION_MASK) != 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   bool isInteger() const { |   bool isInteger() const { | ||||||
|     return type() == VALUE_IS_POSITIVE_INTEGER || |     return type() == VALUE_IS_POSITIVE_INTEGER || | ||||||
|            type() == VALUE_IS_NEGATIVE_INTEGER; |            type() == VALUE_IS_NEGATIVE_INTEGER; | ||||||
| @@ -153,12 +157,11 @@ class VariantData { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool isString() const { |   bool isString() const { | ||||||
|     return (type() == VALUE_IS_LINKED_STRING || |     return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING; | ||||||
|             type() == VALUE_IS_OWNED_STRING); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool isObject() const { |   bool isObject() const { | ||||||
|     return type() == VALUE_IS_OBJECT; |     return (_flags & VALUE_IS_OBJECT) != 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool isNull() const { |   bool isNull() const { | ||||||
| @@ -275,20 +278,35 @@ class VariantData { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t nesting() const { |   size_t nesting() const { | ||||||
|     switch (type()) { |     return isCollection() ? _content.asCollection.nesting() : 0; | ||||||
|       case VALUE_IS_OBJECT: |  | ||||||
|       case VALUE_IS_ARRAY: |  | ||||||
|         return _content.asCollection.nesting(); |  | ||||||
|       default: |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|     if (type() == VALUE_IS_OBJECT || type() == VALUE_IS_ARRAY) |     return isCollection() ? _content.asCollection.size() : 0; | ||||||
|       return _content.asCollection.size(); |   } | ||||||
|     else |  | ||||||
|       return 0; |   VariantData *get(size_t index) const { | ||||||
|  |     return isArray() ? _content.asCollection.get(index) : 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   VariantData *get(TKey key) const { | ||||||
|  |     return isObject() ? _content.asCollection.get(key) : 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   VariantData *getOrCreate(TKey key, MemoryPool *pool) { | ||||||
|  |     if (isNull()) toObject(); | ||||||
|  |     if (!isObject()) return 0; | ||||||
|  |     VariantData *var = _content.asCollection.get(key); | ||||||
|  |     if (var) return var; | ||||||
|  |     return _content.asCollection.add(key, pool); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   VariantData *add(MemoryPool *pool) { | ||||||
|  |     if (isNull()) toArray(); | ||||||
|  |     if (!isArray()) return 0; | ||||||
|  |     return _content.asCollection.add(pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   | |||||||
| @@ -146,4 +146,20 @@ inline CollectionData *variantToObject(VariantData *var) { | |||||||
|   return &var->toObject(); |   return &var->toObject(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline NO_INLINE VariantData *variantAdd(VariantData *var, MemoryPool *pool) { | ||||||
|  |   return var != 0 ? var->add(pool) : 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TKey> | ||||||
|  | NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TKey *key, | ||||||
|  |                                           MemoryPool *pool) { | ||||||
|  |   return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TKey> | ||||||
|  | NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TKey &key, | ||||||
|  |                                           MemoryPool *pool) { | ||||||
|  |   return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -60,37 +60,11 @@ inline const char* VariantData::asString() const { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool VariantRef::set(ArrayRef array) const { | template <typename TVariant> | ||||||
|   return to<ArrayRef>().copyFrom(array); | typename enable_if<IsVisitable<TVariant>::value, bool>::type VariantRef::set( | ||||||
| } |     const TVariant &value) const { | ||||||
|  |   VariantConstRef v = value; | ||||||
| inline bool VariantRef::set(ArrayConstRef array) const { |   return variantCopyFrom(_data, v._data, _pool); | ||||||
|   return to<ArrayRef>().copyFrom(array); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool VariantRef::set(const ArraySubscript& value) const { |  | ||||||
|   return set(value.as<VariantRef>()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool VariantRef::set(ObjectRef object) const { |  | ||||||
|   return to<ObjectRef>().copyFrom(object); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool VariantRef::set(ObjectConstRef object) const { |  | ||||||
|   return to<ObjectRef>().copyFrom(object); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TString> |  | ||||||
| inline bool VariantRef::set(const ObjectSubscript<TString>& value) const { |  | ||||||
|   return set(value.template as<VariantRef>()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool VariantRef::set(VariantConstRef value) const { |  | ||||||
|   return variantCopyFrom(_data, value._data, _pool); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool VariantRef::set(VariantRef value) const { |  | ||||||
|   return variantCopyFrom(_data, value._data, _pool); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| @@ -128,4 +102,32 @@ inline VariantConstRef VariantConstRef::operator[](size_t index) const { | |||||||
|   return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index]; |   return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline VariantRef VariantRef::add() const { | ||||||
|  |   return VariantRef(_pool, variantAdd(_data, _pool)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline VariantRef VariantRef::get(size_t index) const { | ||||||
|  |   return VariantRef(_pool, _data != 0 ? _data->get(index) : 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TKey> | ||||||
|  | inline VariantRef VariantRef::get(TKey *key) const { | ||||||
|  |   return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TKey> | ||||||
|  | inline typename enable_if<IsString<TKey>::value, VariantRef>::type | ||||||
|  | VariantRef::get(const TKey &key) const { | ||||||
|  |   return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TKey> | ||||||
|  | inline VariantRef VariantRef::getOrCreate(TKey *key) const { | ||||||
|  |   return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TKey> | ||||||
|  | inline VariantRef VariantRef::getOrCreate(const TKey &key) const { | ||||||
|  |   return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); | ||||||
|  | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -23,6 +23,9 @@ namespace ARDUINOJSON_NAMESPACE { | |||||||
| class ArrayRef; | class ArrayRef; | ||||||
| class ObjectRef; | class ObjectRef; | ||||||
|  |  | ||||||
|  | template <typename, typename> | ||||||
|  | class MemberProxy; | ||||||
|  |  | ||||||
| // Contains the methods shared by VariantRef and VariantConstRef | // Contains the methods shared by VariantRef and VariantConstRef | ||||||
| template <typename TData> | template <typename TData> | ||||||
| class VariantRefBase { | class VariantRefBase { | ||||||
| @@ -207,16 +210,15 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|     return variantSetLinkedString(_data, value); |     return variantSetLinkedString(_data, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool set(VariantConstRef value) const; |   // set(VariantRef) | ||||||
|   bool set(VariantRef value) const; |   // set(VariantConstRef) | ||||||
|  |   // set(ArrayRef) | ||||||
|   FORCE_INLINE bool set(ArrayRef array) const; |   // set(ArrayConstRef) | ||||||
|   FORCE_INLINE bool set(ArrayConstRef array) const; |   // set(ObjectRef) | ||||||
|   FORCE_INLINE bool set(const ArraySubscript &) const; |   // set(ObjecConstRef) | ||||||
|   FORCE_INLINE bool set(ObjectRef object) const; |   template <typename TVariant> | ||||||
|   FORCE_INLINE bool set(ObjectConstRef object) const; |   typename enable_if<IsVisitable<TVariant>::value, bool>::type set( | ||||||
|   template <typename TString> |       const TVariant &value) const; | ||||||
|   FORCE_INLINE bool set(const ObjectSubscript<TString> &) const; |  | ||||||
|  |  | ||||||
|   // Get the variant as the specified type. |   // Get the variant as the specified type. | ||||||
|   // |   // | ||||||
| @@ -278,6 +280,26 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|   typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to() |   typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to() | ||||||
|       const; |       const; | ||||||
|  |  | ||||||
|  |   VariantRef add() const; | ||||||
|  |   using ArrayShortcuts::add; | ||||||
|  |  | ||||||
|  |   FORCE_INLINE VariantRef get(size_t) const; | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE VariantRef get(TKey *) const; | ||||||
|  |  | ||||||
|  |   // get(const char*) | ||||||
|  |   // get(const __FlashStringHelper*) | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantRef>::type get( | ||||||
|  |       const TKey &) const; | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(TKey *) const; | ||||||
|  |  | ||||||
|  |   template <typename TKey> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(const TKey &) const; | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   MemoryPool *_pool; |   MemoryPool *_pool; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -71,6 +71,7 @@ if(MSVC) | |||||||
| 	) | 	) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | add_subdirectory(ElementProxy) | ||||||
| add_subdirectory(IntegrationTests) | add_subdirectory(IntegrationTests) | ||||||
| add_subdirectory(JsonArray) | add_subdirectory(JsonArray) | ||||||
| add_subdirectory(JsonDeserializer) | add_subdirectory(JsonDeserializer) | ||||||
| @@ -78,10 +79,11 @@ add_subdirectory(JsonDocument) | |||||||
| add_subdirectory(JsonObject) | add_subdirectory(JsonObject) | ||||||
| add_subdirectory(JsonSerializer) | add_subdirectory(JsonSerializer) | ||||||
| add_subdirectory(JsonVariant) | add_subdirectory(JsonVariant) | ||||||
| add_subdirectory(TextFormatter) | add_subdirectory(MemberProxy) | ||||||
| add_subdirectory(MemoryPool) | add_subdirectory(MemoryPool) | ||||||
| add_subdirectory(Misc) | add_subdirectory(Misc) | ||||||
| add_subdirectory(MixedConfiguration) | add_subdirectory(MixedConfiguration) | ||||||
| add_subdirectory(MsgPackDeserializer) | add_subdirectory(MsgPackDeserializer) | ||||||
| add_subdirectory(MsgPackSerializer) | add_subdirectory(MsgPackSerializer) | ||||||
| add_subdirectory(Numbers) | add_subdirectory(Numbers) | ||||||
|  | add_subdirectory(TextFormatter) | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								test/ElementProxy/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								test/ElementProxy/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | # ArduinoJson - arduinojson.org | ||||||
|  | # Copyright Benoit Blanchon 2014-2018 | ||||||
|  | # MIT License | ||||||
|  |  | ||||||
|  | add_executable(ElementProxyTests | ||||||
|  | 	add.cpp | ||||||
|  | 	set.cpp | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | target_link_libraries(ElementProxyTests catch) | ||||||
|  | add_test(ElementProxy ElementProxyTests) | ||||||
							
								
								
									
										26
									
								
								test/ElementProxy/add.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								test/ElementProxy/add.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|  |  | ||||||
|  | TEST_CASE("ElementProxy::add()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   doc.add(); | ||||||
|  |   ElementProxy<JsonDocument&> ep = doc[0]; | ||||||
|  |  | ||||||
|  |   SECTION("add(int)") { | ||||||
|  |     ep.add(42); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "[[42]]"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("add(const char*)") { | ||||||
|  |     ep.add("world"); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "[[\"world\"]]"); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								test/ElementProxy/set.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								test/ElementProxy/set.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|  |  | ||||||
|  | TEST_CASE("ElementProxy::set()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   doc.add(); | ||||||
|  |   ElementProxy<JsonDocument&> ep = doc[0]; | ||||||
|  |  | ||||||
|  |   SECTION("set(int)") { | ||||||
|  |     ep.set(42); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "[42]"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("set(const char*)") { | ||||||
|  |     ep.set("world"); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "[\"world\"]"); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -3,9 +3,11 @@ | |||||||
| # MIT License | # MIT License | ||||||
|  |  | ||||||
| add_executable(JsonDocumentTests | add_executable(JsonDocumentTests | ||||||
|  | 	add.cpp | ||||||
|  | 	createNested.cpp | ||||||
| 	DynamicJsonDocument.cpp | 	DynamicJsonDocument.cpp | ||||||
| 	nesting.cpp |  | ||||||
| 	isNull.cpp | 	isNull.cpp | ||||||
|  | 	nesting.cpp | ||||||
| 	StaticJsonDocument.cpp | 	StaticJsonDocument.cpp | ||||||
| 	subscript.cpp | 	subscript.cpp | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								test/JsonDocument/add.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								test/JsonDocument/add.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonDocument::add()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |  | ||||||
|  |   SECTION("integer") { | ||||||
|  |     doc.add(42); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "[42]"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("const char*") { | ||||||
|  |     doc.add("hello"); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "[\"hello\"]"); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										66
									
								
								test/JsonDocument/createNested.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								test/JsonDocument/createNested.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonDocument::createNestedArray()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |  | ||||||
|  |   SECTION("promotes to array") { | ||||||
|  |     doc.createNestedArray(); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.is<JsonArray>()); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonDocument::createNestedArray(key)") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |  | ||||||
|  |   SECTION("key is const char*") { | ||||||
|  |     SECTION("promotes to object") { | ||||||
|  |       doc.createNestedArray("hello"); | ||||||
|  |  | ||||||
|  |       REQUIRE(doc.is<JsonObject>()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("key is std::string") { | ||||||
|  |     SECTION("promotes to object") { | ||||||
|  |       doc.createNestedArray(std::string("hello")); | ||||||
|  |  | ||||||
|  |       REQUIRE(doc.is<JsonObject>()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonDocument::createNestedObject()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |  | ||||||
|  |   SECTION("promotes to array") { | ||||||
|  |     doc.createNestedObject(); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.is<JsonArray>()); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonDocument::createNestedObject(key)") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |  | ||||||
|  |   SECTION("key is const char*") { | ||||||
|  |     SECTION("promotes to object") { | ||||||
|  |       doc.createNestedObject("hello"); | ||||||
|  |  | ||||||
|  |       REQUIRE(doc.is<JsonObject>()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("key is std::string") { | ||||||
|  |     SECTION("promotes to object") { | ||||||
|  |       doc.createNestedObject(std::string("hello")); | ||||||
|  |  | ||||||
|  |       REQUIRE(doc.is<JsonObject>()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -21,6 +21,11 @@ TEST_CASE("JsonDocument::operator[]") { | |||||||
|       REQUIRE(doc[std::string("hello")] == "world"); |       REQUIRE(doc[std::string("hello")] == "world"); | ||||||
|       REQUIRE(cdoc[std::string("hello")] == "world"); |       REQUIRE(cdoc[std::string("hello")] == "world"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     SECTION("supports operator|") { | ||||||
|  |       REQUIRE((doc["hello"] | "nope") == std::string("world")); | ||||||
|  |       REQUIRE((doc["world"] | "nope") == std::string("nope")); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("array") { |   SECTION("array") { | ||||||
| @@ -30,3 +35,11 @@ TEST_CASE("JsonDocument::operator[]") { | |||||||
|     REQUIRE(cdoc[1] == "world"); |     REQUIRE(cdoc[1] == "world"); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonDocument automatically promotes to object") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |  | ||||||
|  |   doc["one"]["two"]["three"] = 4; | ||||||
|  |  | ||||||
|  |   REQUIRE(doc["one"]["two"]["three"] == 4); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ void check(T value, const std::string &expected) { | |||||||
|   REQUIRE(expected.size() == returnValue); |   REQUIRE(expected.size() == returnValue); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("serializeJson(JsonObjectSubscript)") { | TEST_CASE("serializeJson(MemberProxy)") { | ||||||
|   DynamicJsonDocument doc(4096); |   DynamicJsonDocument doc(4096); | ||||||
|   deserializeJson(doc, "{\"hello\":42}"); |   deserializeJson(doc, "{\"hello\":42}"); | ||||||
|   JsonObject obj = doc.as<JsonObject>(); |   JsonObject obj = doc.as<JsonObject>(); | ||||||
| @@ -23,7 +23,7 @@ TEST_CASE("serializeJson(JsonObjectSubscript)") { | |||||||
|   REQUIRE(result == "42"); |   REQUIRE(result == "42"); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("serializeJson(JsonArraySubscript)") { | TEST_CASE("serializeJson(ElementProxy)") { | ||||||
|   DynamicJsonDocument doc(4096); |   DynamicJsonDocument doc(4096); | ||||||
|   deserializeJson(doc, "[42]"); |   deserializeJson(doc, "[42]"); | ||||||
|   JsonArray arr = doc.as<JsonArray>(); |   JsonArray arr = doc.as<JsonArray>(); | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ TEST_CASE("operator<<(std::ostream)") { | |||||||
|     REQUIRE("{\"key\":\"value\"}" == os.str()); |     REQUIRE("{\"key\":\"value\"}" == os.str()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("JsonObjectSubscript") { |   SECTION("MemberProxy") { | ||||||
|     JsonObject object = doc.to<JsonObject>(); |     JsonObject object = doc.to<JsonObject>(); | ||||||
|     object["key"] = "value"; |     object["key"] = "value"; | ||||||
|  |  | ||||||
| @@ -55,7 +55,7 @@ TEST_CASE("operator<<(std::ostream)") { | |||||||
|     REQUIRE("[\"value\"]" == os.str()); |     REQUIRE("[\"value\"]" == os.str()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("JsonArraySubscript") { |   SECTION("ElementProxy") { | ||||||
|     JsonArray array = doc.to<JsonArray>(); |     JsonArray array = doc.to<JsonArray>(); | ||||||
|     array.add("value"); |     array.add("value"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,18 +3,21 @@ | |||||||
| # MIT License | # MIT License | ||||||
|  |  | ||||||
| add_executable(JsonVariantTests | add_executable(JsonVariantTests | ||||||
|  | 	add.cpp | ||||||
| 	as.cpp | 	as.cpp | ||||||
| 	compare.cpp | 	compare.cpp | ||||||
| 	copy.cpp | 	copy.cpp | ||||||
|  | 	createNested.cpp | ||||||
| 	get.cpp | 	get.cpp | ||||||
| 	is.cpp | 	is.cpp | ||||||
| 	isnull.cpp | 	isnull.cpp | ||||||
| 	memoryUsage.cpp | 	memoryUsage.cpp | ||||||
| 	nesting.cpp |  | ||||||
| 	misc.cpp | 	misc.cpp | ||||||
|  | 	nesting.cpp | ||||||
| 	or.cpp | 	or.cpp | ||||||
| 	set.cpp | 	set.cpp | ||||||
| 	subscript.cpp | 	subscript.cpp | ||||||
|  | 	types.cpp | ||||||
| 	undefined.cpp | 	undefined.cpp | ||||||
| ) | ) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										39
									
								
								test/JsonVariant/add.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								test/JsonVariant/add.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | static const char* null = 0; | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonVariant::add()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   JsonVariant var = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|  |   SECTION("No argument") { | ||||||
|  |     JsonVariant nested = var.add(); | ||||||
|  |  | ||||||
|  |     REQUIRE(var.is<JsonArray>() == true); | ||||||
|  |     REQUIRE(nested.isNull() == true); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("integer") { | ||||||
|  |     var.add(42); | ||||||
|  |  | ||||||
|  |     REQUIRE(var.as<std::string>() == "[42]"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("const char*") { | ||||||
|  |     var.add("hello"); | ||||||
|  |  | ||||||
|  |     REQUIRE(var.as<std::string>() == "[\"hello\"]"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("std::string") { | ||||||
|  |     var.add(std::string("hello")); | ||||||
|  |  | ||||||
|  |     REQUIRE(var.as<std::string>() == "[\"hello\"]"); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										88
									
								
								test/JsonVariant/createNested.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								test/JsonVariant/createNested.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | static const char* null = 0; | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonVariant::createNestedObject()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   JsonVariant variant = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|  |   SECTION("promotes to array") { | ||||||
|  |     JsonObject obj = variant.createNestedObject(); | ||||||
|  |     obj["value"] = "42"; | ||||||
|  |  | ||||||
|  |     REQUIRE(variant.is<JsonArray>() == true); | ||||||
|  |     REQUIRE(variant[0]["value"] == 42); | ||||||
|  |     REQUIRE(obj.isNull() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("works on MemberProxy") { | ||||||
|  |     JsonObject obj = variant["items"].createNestedObject(); | ||||||
|  |     obj["value"] = "42"; | ||||||
|  |  | ||||||
|  |     REQUIRE(variant["items"][0]["value"] == 42); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonVariant::createNestedArray()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   JsonVariant variant = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|  |   SECTION("promotes to array") { | ||||||
|  |     JsonArray arr = variant.createNestedArray(); | ||||||
|  |  | ||||||
|  |     REQUIRE(variant.is<JsonArray>() == true); | ||||||
|  |     REQUIRE(arr.isNull() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("works on MemberProxy") { | ||||||
|  |     JsonArray arr = variant["items"].createNestedArray(); | ||||||
|  |     arr.add("42"); | ||||||
|  |  | ||||||
|  |     REQUIRE(variant["items"][0][0] == 42); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonVariant::createNestedObject(key)") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   JsonVariant variant = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|  |   SECTION("promotes to object") { | ||||||
|  |     JsonObject obj = variant.createNestedObject("weather"); | ||||||
|  |     obj["temp"] = "42"; | ||||||
|  |  | ||||||
|  |     REQUIRE(variant.is<JsonObject>() == true); | ||||||
|  |     REQUIRE(variant["weather"]["temp"] == 42); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("works on MemberProxy") { | ||||||
|  |     JsonObject obj = variant["status"].createNestedObject("weather"); | ||||||
|  |     obj["temp"] = "42"; | ||||||
|  |  | ||||||
|  |     REQUIRE(variant["status"]["weather"]["temp"] == 42); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonVariant::createNestedArray(key)") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   JsonVariant variant = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|  |   SECTION("promotes to object") { | ||||||
|  |     JsonArray arr = variant.createNestedArray("items"); | ||||||
|  |  | ||||||
|  |     REQUIRE(variant.is<JsonObject>() == true); | ||||||
|  |     REQUIRE(arr.isNull() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("works on MemberProxy") { | ||||||
|  |     JsonArray arr = variant["weather"].createNestedArray("temp"); | ||||||
|  |     arr.add("42"); | ||||||
|  |  | ||||||
|  |     REQUIRE(variant["weather"]["temp"][0] == 42); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -3,138 +3,27 @@ | |||||||
| // MIT License | // MIT License | ||||||
|  |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
| #include <stdint.h> |  | ||||||
| #include <catch.hpp> | #include <catch.hpp> | ||||||
| #include <limits> |  | ||||||
|  |  | ||||||
| template <typename T> | TEST_CASE("JsonVariant::get()") { | ||||||
| void checkValue(T expected) { |  | ||||||
|   DynamicJsonDocument doc(4096); |   DynamicJsonDocument doc(4096); | ||||||
|   JsonVariant variant = doc.to<JsonVariant>(); |   JsonVariant var = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|   variant.set(expected); |   SECTION("get(const char*)") { | ||||||
|   REQUIRE(expected == variant.as<T>()); |     var["value"] = 42; | ||||||
|  |  | ||||||
|  |     REQUIRE(var.get("value") == 42); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| template <typename T> |   SECTION("get(std::string)") { | ||||||
| void checkReference(T &expected) { |     var["value"] = 42; | ||||||
|   JsonVariant variant = expected; |  | ||||||
|   REQUIRE(expected == variant.as<T &>()); |     REQUIRE(var.get(std::string("value")) == 42); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| template <typename T> |   SECTION("get(int)") { | ||||||
| void checkNumericType() { |     var.add().set(42); | ||||||
|   DynamicJsonDocument docMin(4096), docMax(4096); |  | ||||||
|   JsonVariant variantMin = docMin.to<JsonVariant>(); |  | ||||||
|   JsonVariant variantMax = docMax.to<JsonVariant>(); |  | ||||||
|  |  | ||||||
|   T min = std::numeric_limits<T>::min(); |     REQUIRE(var.get(0) == 42); | ||||||
|   T max = std::numeric_limits<T>::max(); |  | ||||||
|  |  | ||||||
|   variantMin.set(min); |  | ||||||
|   variantMax.set(max); |  | ||||||
|  |  | ||||||
|   REQUIRE(min == variantMin.as<T>()); |  | ||||||
|   REQUIRE(max == variantMax.as<T>()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| TEST_CASE("JsonVariant set()/get()") { |  | ||||||
| #if ARDUINOJSON_USE_LONG_LONG |  | ||||||
|   SECTION("SizeOfJsonInteger") { |  | ||||||
|     REQUIRE(8 == sizeof(JsonInteger)); |  | ||||||
|   } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   SECTION("Null") { |  | ||||||
|     checkValue<const char *>(NULL); |  | ||||||
|   } |  | ||||||
|   SECTION("const char*") { |  | ||||||
|     checkValue<const char *>("hello"); |  | ||||||
|   } |  | ||||||
|   SECTION("std::string") { |  | ||||||
|     checkValue<std::string>("hello"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("False") { |  | ||||||
|     checkValue<bool>(false); |  | ||||||
|   } |  | ||||||
|   SECTION("True") { |  | ||||||
|     checkValue<bool>(true); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("Double") { |  | ||||||
|     checkNumericType<double>(); |  | ||||||
|   } |  | ||||||
|   SECTION("Float") { |  | ||||||
|     checkNumericType<float>(); |  | ||||||
|   } |  | ||||||
|   SECTION("Char") { |  | ||||||
|     checkNumericType<char>(); |  | ||||||
|   } |  | ||||||
|   SECTION("SChar") { |  | ||||||
|     checkNumericType<signed char>(); |  | ||||||
|   } |  | ||||||
|   SECTION("SInt") { |  | ||||||
|     checkNumericType<signed int>(); |  | ||||||
|   } |  | ||||||
|   SECTION("SLong") { |  | ||||||
|     checkNumericType<signed long>(); |  | ||||||
|   } |  | ||||||
|   SECTION("SShort") { |  | ||||||
|     checkNumericType<signed short>(); |  | ||||||
|   } |  | ||||||
|   SECTION("UChar") { |  | ||||||
|     checkNumericType<unsigned char>(); |  | ||||||
|   } |  | ||||||
|   SECTION("UInt") { |  | ||||||
|     checkNumericType<unsigned int>(); |  | ||||||
|   } |  | ||||||
|   SECTION("ULong") { |  | ||||||
|     checkNumericType<unsigned long>(); |  | ||||||
|   } |  | ||||||
|   SECTION("UShort") { |  | ||||||
|     checkNumericType<unsigned short>(); |  | ||||||
|   } |  | ||||||
| #if ARDUINOJSON_USE_LONG_LONG |  | ||||||
|   SECTION("LongLong") { |  | ||||||
|     checkNumericType<unsigned long long>(); |  | ||||||
|   } |  | ||||||
|   SECTION("ULongLong") { |  | ||||||
|     checkNumericType<unsigned long long>(); |  | ||||||
|   } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   SECTION("Int8") { |  | ||||||
|     checkNumericType<int8_t>(); |  | ||||||
|   } |  | ||||||
|   SECTION("Uint8") { |  | ||||||
|     checkNumericType<uint8_t>(); |  | ||||||
|   } |  | ||||||
|   SECTION("Int16") { |  | ||||||
|     checkNumericType<int16_t>(); |  | ||||||
|   } |  | ||||||
|   SECTION("Uint16") { |  | ||||||
|     checkNumericType<uint16_t>(); |  | ||||||
|   } |  | ||||||
|   SECTION("Int32") { |  | ||||||
|     checkNumericType<int32_t>(); |  | ||||||
|   } |  | ||||||
|   SECTION("Uint32") { |  | ||||||
|     checkNumericType<uint32_t>(); |  | ||||||
|   } |  | ||||||
| #if ARDUINOJSON_USE_LONG_LONG |  | ||||||
|   SECTION("Int64") { |  | ||||||
|     checkNumericType<int64_t>(); |  | ||||||
|   } |  | ||||||
|   SECTION("Uint64") { |  | ||||||
|     checkNumericType<uint64_t>(); |  | ||||||
|   } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   SECTION("CanStoreObject") { |  | ||||||
|     DynamicJsonDocument doc(4096); |  | ||||||
|     JsonObject object = doc.to<JsonObject>(); |  | ||||||
|  |  | ||||||
|     checkValue<JsonObject>(object); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -30,7 +30,8 @@ TEST_CASE("JsonVariant::operator[]") { | |||||||
|       array.add("element at index 1"); |       array.add("element at index 1"); | ||||||
|  |  | ||||||
|       REQUIRE(2 == var.size()); |       REQUIRE(2 == var.size()); | ||||||
|       REQUIRE(std::string("element at index 0") == var[0]); |       var[0].as<std::string>(); | ||||||
|  |       // REQUIRE(std::string("element at index 0") == ); | ||||||
|       REQUIRE(std::string("element at index 1") == var[1]); |       REQUIRE(std::string("element at index 1") == var[1]); | ||||||
|       REQUIRE(std::string("element at index 0") == |       REQUIRE(std::string("element at index 0") == | ||||||
|               var[static_cast<unsigned char>(0)]);  // issue #381 |               var[static_cast<unsigned char>(0)]);  // issue #381 | ||||||
| @@ -171,4 +172,24 @@ TEST_CASE("JsonVariantConst::operator[]") { | |||||||
|       REQUIRE(cvar[0].isNull()); |       REQUIRE(cvar[0].isNull()); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("Auto promote null JsonVariant to JsonObject") { | ||||||
|  |     var["hello"] = "world"; | ||||||
|  |  | ||||||
|  |     REQUIRE(var.is<JsonObject>() == true); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("Don't auto promote non-null JsonVariant to JsonObject") { | ||||||
|  |     var.set(42); | ||||||
|  |     var["hello"] = "world"; | ||||||
|  |  | ||||||
|  |     REQUIRE(var.is<JsonObject>() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("Don't auto promote null JsonVariant to JsonObject when reading") { | ||||||
|  |     const char* value = var["hello"]; | ||||||
|  |  | ||||||
|  |     REQUIRE(var.is<JsonObject>() == false); | ||||||
|  |     REQUIRE(value == 0); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										140
									
								
								test/JsonVariant/types.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								test/JsonVariant/types.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  | #include <limits> | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | void checkValue(T expected) { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   JsonVariant variant = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|  |   variant.set(expected); | ||||||
|  |   REQUIRE(expected == variant.as<T>()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | void checkReference(T &expected) { | ||||||
|  |   JsonVariant variant = expected; | ||||||
|  |   REQUIRE(expected == variant.as<T &>()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | void checkNumericType() { | ||||||
|  |   DynamicJsonDocument docMin(4096), docMax(4096); | ||||||
|  |   JsonVariant variantMin = docMin.to<JsonVariant>(); | ||||||
|  |   JsonVariant variantMax = docMax.to<JsonVariant>(); | ||||||
|  |  | ||||||
|  |   T min = std::numeric_limits<T>::min(); | ||||||
|  |   T max = std::numeric_limits<T>::max(); | ||||||
|  |  | ||||||
|  |   variantMin.set(min); | ||||||
|  |   variantMax.set(max); | ||||||
|  |  | ||||||
|  |   REQUIRE(min == variantMin.as<T>()); | ||||||
|  |   REQUIRE(max == variantMax.as<T>()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonVariant set()/get()") { | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG | ||||||
|  |   SECTION("SizeOfJsonInteger") { | ||||||
|  |     REQUIRE(8 == sizeof(JsonInteger)); | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   SECTION("Null") { | ||||||
|  |     checkValue<const char *>(NULL); | ||||||
|  |   } | ||||||
|  |   SECTION("const char*") { | ||||||
|  |     checkValue<const char *>("hello"); | ||||||
|  |   } | ||||||
|  |   SECTION("std::string") { | ||||||
|  |     checkValue<std::string>("hello"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("False") { | ||||||
|  |     checkValue<bool>(false); | ||||||
|  |   } | ||||||
|  |   SECTION("True") { | ||||||
|  |     checkValue<bool>(true); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("Double") { | ||||||
|  |     checkNumericType<double>(); | ||||||
|  |   } | ||||||
|  |   SECTION("Float") { | ||||||
|  |     checkNumericType<float>(); | ||||||
|  |   } | ||||||
|  |   SECTION("Char") { | ||||||
|  |     checkNumericType<char>(); | ||||||
|  |   } | ||||||
|  |   SECTION("SChar") { | ||||||
|  |     checkNumericType<signed char>(); | ||||||
|  |   } | ||||||
|  |   SECTION("SInt") { | ||||||
|  |     checkNumericType<signed int>(); | ||||||
|  |   } | ||||||
|  |   SECTION("SLong") { | ||||||
|  |     checkNumericType<signed long>(); | ||||||
|  |   } | ||||||
|  |   SECTION("SShort") { | ||||||
|  |     checkNumericType<signed short>(); | ||||||
|  |   } | ||||||
|  |   SECTION("UChar") { | ||||||
|  |     checkNumericType<unsigned char>(); | ||||||
|  |   } | ||||||
|  |   SECTION("UInt") { | ||||||
|  |     checkNumericType<unsigned int>(); | ||||||
|  |   } | ||||||
|  |   SECTION("ULong") { | ||||||
|  |     checkNumericType<unsigned long>(); | ||||||
|  |   } | ||||||
|  |   SECTION("UShort") { | ||||||
|  |     checkNumericType<unsigned short>(); | ||||||
|  |   } | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG | ||||||
|  |   SECTION("LongLong") { | ||||||
|  |     checkNumericType<unsigned long long>(); | ||||||
|  |   } | ||||||
|  |   SECTION("ULongLong") { | ||||||
|  |     checkNumericType<unsigned long long>(); | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   SECTION("Int8") { | ||||||
|  |     checkNumericType<int8_t>(); | ||||||
|  |   } | ||||||
|  |   SECTION("Uint8") { | ||||||
|  |     checkNumericType<uint8_t>(); | ||||||
|  |   } | ||||||
|  |   SECTION("Int16") { | ||||||
|  |     checkNumericType<int16_t>(); | ||||||
|  |   } | ||||||
|  |   SECTION("Uint16") { | ||||||
|  |     checkNumericType<uint16_t>(); | ||||||
|  |   } | ||||||
|  |   SECTION("Int32") { | ||||||
|  |     checkNumericType<int32_t>(); | ||||||
|  |   } | ||||||
|  |   SECTION("Uint32") { | ||||||
|  |     checkNumericType<uint32_t>(); | ||||||
|  |   } | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG | ||||||
|  |   SECTION("Int64") { | ||||||
|  |     checkNumericType<int64_t>(); | ||||||
|  |   } | ||||||
|  |   SECTION("Uint64") { | ||||||
|  |     checkNumericType<uint64_t>(); | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   SECTION("CanStoreObject") { | ||||||
|  |     DynamicJsonDocument doc(4096); | ||||||
|  |     JsonObject object = doc.to<JsonObject>(); | ||||||
|  |  | ||||||
|  |     checkValue<JsonObject>(object); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								test/MemberProxy/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								test/MemberProxy/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | # ArduinoJson - arduinojson.org | ||||||
|  | # Copyright Benoit Blanchon 2014-2018 | ||||||
|  | # MIT License | ||||||
|  |  | ||||||
|  | add_executable(MemberProxyTests | ||||||
|  | 	add.cpp | ||||||
|  | 	subscript.cpp | ||||||
|  | 	set.cpp | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | target_link_libraries(MemberProxyTests catch) | ||||||
|  | add_test(MemberProxy MemberProxyTests) | ||||||
							
								
								
									
										25
									
								
								test/MemberProxy/add.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/MemberProxy/add.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|  |  | ||||||
|  | TEST_CASE("MemberProxy::add()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; | ||||||
|  |  | ||||||
|  |   SECTION("add(int)") { | ||||||
|  |     mp.add(42); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "{\"hello\":[42]}"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("add(const char*)") { | ||||||
|  |     mp.add("world"); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}"); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								test/MemberProxy/set.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/MemberProxy/set.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|  |  | ||||||
|  | TEST_CASE("MemberProxy::set()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; | ||||||
|  |  | ||||||
|  |   SECTION("set(int)") { | ||||||
|  |     mp.set(42); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "{\"hello\":42}"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("set(const char*)") { | ||||||
|  |     mp.set("world"); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								test/MemberProxy/subscript.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								test/MemberProxy/subscript.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|  |  | ||||||
|  | TEST_CASE("MemberProxy::operator[]") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; | ||||||
|  |  | ||||||
|  |   SECTION("set integer") { | ||||||
|  |     mp["world"] = 42; | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "{\"hello\":{\"world\":42}}"); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -54,10 +54,10 @@ TEST_CASE("Polyfills/type_traits") { | |||||||
|     CHECK(IsVisitable<VariantRef>::value == true); |     CHECK(IsVisitable<VariantRef>::value == true); | ||||||
|     CHECK(IsVisitable<VariantConstRef>::value == true); |     CHECK(IsVisitable<VariantConstRef>::value == true); | ||||||
|     CHECK(IsVisitable<ArrayRef>::value == true); |     CHECK(IsVisitable<ArrayRef>::value == true); | ||||||
|     CHECK(IsVisitable<ArraySubscript>::value == true); |     CHECK(IsVisitable<ElementProxy<ArrayRef> >::value == true); | ||||||
|     CHECK(IsVisitable<ArrayConstRef>::value == true); |     CHECK(IsVisitable<ArrayConstRef>::value == true); | ||||||
|     CHECK(IsVisitable<ObjectRef>::value == true); |     CHECK(IsVisitable<ObjectRef>::value == true); | ||||||
|     CHECK(IsVisitable<ObjectSubscript<const char*> >::value == true); |     CHECK((IsVisitable<MemberProxy<ObjectRef, const char*> >::value == true)); | ||||||
|     CHECK(IsVisitable<ObjectConstRef>::value == true); |     CHECK(IsVisitable<ObjectConstRef>::value == true); | ||||||
|     CHECK(IsVisitable<DynamicJsonDocument>::value == true); |     CHECK(IsVisitable<DynamicJsonDocument>::value == true); | ||||||
|     CHECK(IsVisitable<StaticJsonDocument<10> >::value == true); |     CHECK(IsVisitable<StaticJsonDocument<10> >::value == true); | ||||||
|   | |||||||
| @@ -147,7 +147,7 @@ TEST_CASE("unsigned char[]") { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("JsonObjectSubscript") { |   SECTION("MemberProxy") { | ||||||
|     SECTION("operator=") {  // issue #416 |     SECTION("operator=") {  // issue #416 | ||||||
|       unsigned char value[] = "world"; |       unsigned char value[] = "world"; | ||||||
|  |  | ||||||
| @@ -181,7 +181,7 @@ TEST_CASE("unsigned char[]") { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("JsonArraySubscript") { |   SECTION("ElementProxy") { | ||||||
|     SECTION("set()") { |     SECTION("set()") { | ||||||
|       unsigned char value[] = "world"; |       unsigned char value[] = "world"; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ void check(T value, const std::string &expected) { | |||||||
|   REQUIRE(expected.size() == returnValue); |   REQUIRE(expected.size() == returnValue); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("serializeMsgPack(JsonObjectSubscript)") { | TEST_CASE("serializeMsgPack(MemberProxy)") { | ||||||
|   DynamicJsonDocument doc(4096); |   DynamicJsonDocument doc(4096); | ||||||
|   deserializeJson(doc, "{\"hello\":42}"); |   deserializeJson(doc, "{\"hello\":42}"); | ||||||
|   JsonObject obj = doc.as<JsonObject>(); |   JsonObject obj = doc.as<JsonObject>(); | ||||||
| @@ -23,7 +23,7 @@ TEST_CASE("serializeMsgPack(JsonObjectSubscript)") { | |||||||
|   REQUIRE(result == "*"); |   REQUIRE(result == "*"); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("serializeMsgPack(JsonArraySubscript)") { | TEST_CASE("serializeMsgPack(ElementProxy)") { | ||||||
|   DynamicJsonDocument doc(4096); |   DynamicJsonDocument doc(4096); | ||||||
|   deserializeJson(doc, "[42]"); |   deserializeJson(doc, "[42]"); | ||||||
|   JsonArray arr = doc.as<JsonArray>(); |   JsonArray arr = doc.as<JsonArray>(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user