8000 `RawJson()` accepts any kind of string and obeys to duplication rules · janelia-arduino/ArduinoJson@bae179e · GitHub
[go: up one dir, main page]

Skip to content

Commit bae179e

Browse files
committed
RawJson() accepts any kind of string and obeys to duplication rules
1 parent 7e4fcb0 commit bae179e

20 files changed

+163
-123
lines changed

CHANGELOG.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@ HEAD
55
----
66

77
* Changed the rules of string duplication (issue #658)
8+
* `RawJson()` accepts any kind of string and obeys to the same rules for duplication
89
* Changed the return type of `strdup()` to `const char*` to prevent double duplication
910
* Marked `strdup()` as deprecated
1011

1112
> ### New rules for string duplication
1213
>
13-
> | type | duplication |
14-
> |:-------------|:------------|
15-
> | const char* | no |
16-
> | char* | ~~no~~ yes |
17-
> | String | yes |
18-
> | std::string | yes |
14+
> | type | duplication |
15+
> |:---------------------------|:------------|
16+
> | const char* | no |
17+
> | char* | ~~no~~ yes |
18+
> | String | yes |
19+
> | std::string | yes |
20+
> | const __FlashStringHelper* | yes |
1921
>
2022
> These new rules make `JsonBuffer::strdup()` useless.
2123

examples/ProgmemExample/ProgmemExample.ino

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ void setup() {
3737
// JsonBuffer.
3838
root["sensor"] = F("gps");
3939

40+
// It works with RawJson too:
41+
root["sensor"] = RawJson(F("\"gps\""));
42+
4043
// You can compare the content of a JsonVariant to a Flash String
4144
if (root["sensor"] == F("gps")) {
4245
// ...

examples/StringExample/StringExample.ino

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ void setup() {
4040
// WARNING: the content of the String will be duplicated in the JsonBuffer.
4141
root["sensor"] = sensor;
4242

43+
// It works with RawJson too:
44+
root["sensor"] = RawJson(sensor);
45+
4346
// You can also concatenate strings
4447
// WARNING: the content of the String will be duplicated in the JsonBuffer.
4548
root[String("sen") + "sor"] = String("gp") + "s";

src/ArduinoJson/Data/ValueSaver.hpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,29 @@ struct ValueSaver {
2323

2424
template <typename Source>
2525
struct ValueSaver<Source, typename TypeTraits::EnableIf<
26-
TypeTraits::IsString<Source>::value>::type> {
26+
StringTraits<Source>::should_duplicate>::type> {
2727
template <typename Destination>
28-
static bool save(JsonBuffer* buffer, Destination& destination,
29-
Source source) {
30-
return StringTraits<Source>::save(source, destination, buffer);
28+
static bool save(JsonBuffer* buffer, Destination& dest, Source source) {
29+
if (!StringTraits<Source>::is_null(source)) {
30+
typename StringTraits<Source>::duplicate_t dup =
31+
StringTraits<Source>::duplicate(source, buffer);
32+
if (!dup) return false;
33+
dest = dup;
34+
} else {
35+
dest = reinterpret_cast<const char*>(0);
36+
}
37+
return true;
38+
}
39+
};
40+
41+
// const char*, const signed char*, const unsigned char*
42+
template <typename Char>
43+
struct ValueSaver<Char*, typename TypeTraits::EnableIf<
44+
!StringTraits<Char*>::should_duplicate>::type> {
45+
template <typename Destination>
46+
static bool save(JsonBuffer*, Destination& dest, Char* source) {
47+
dest = reinterpret_cast<const char*>(source);
48+
return true;
3149
}
3250
};
3351
}

src/ArduinoJson/JsonObjectSubscript.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class JsonObjectSubscript
4646
// operator=(TValue);
4747
// TValue = char*, const char*, const FlashStringHelper*
4848
template <typename TValue>
49-
FORCE_INLINE this_type& operator=(const TValue* src) {
49+
FORCE_INLINE this_type& operator=(TValue* src) {
5050
_object.set(_key, src);
5151
return *this;
5252
}

src/ArduinoJson/JsonVariant.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
117117
}
118118

119119
// Create a JsonVariant containing an unparsed string
120-
JsonVariant(RawJson value) {
120+
JsonVariant(Internals::RawJsonString<const char *> value) {
121121
_type = Internals::JSON_UNPARSED;
122122
_content.asString = value;
123123
}

src/ArduinoJson/JsonVariantComparisons.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,17 +104,18 @@ class JsonVariantComparisons {
104104
}
105105

106106
template <typename TString>
107-
typename TypeTraits::EnableIf<TypeTraits::IsString<TString>::value,
107+
typename TypeTraits::EnableIf<Internals::StringTraits<TString>::has_equals,
108108
bool>::type
109109
equals(const TString &comparand) const {
110110
const char *value = as<const char *>();
111111
return Internals::StringTraits<TString>::equals(comparand, value);
112112
}
113113

114114
template <typename TComparand>
115-
typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value &&
116-
!TypeTraits::IsString<TComparand>::value,
117-
bool>::type
115+
typename TypeTraits::EnableIf<
116+
!TypeTraits::IsVariant<TComparand>::value &&
117+
!Internals::StringTraits<TComparand>::has_equals,
118+
bool>::type
118119
equals(const TComparand &comparand) const {
119120
return as<TComparand>() == comparand;
120121
}

src/ArduinoJson/RawJson.hpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,41 @@
66

77
namespace ArduinoJson {
88

9+
namespace Internals {
910
// A special type of data that can be used to insert pregenerated JSON portions.
10-
class RawJson {
11+
template <typename T>
12+
class RawJsonString {
1113
public:
12-
explicit RawJson(const char* str) : _str(str) {}
13-
operator const char*() const {
14+
explicit RawJsonString(T str) : _str(str) {}
15+
operator T() const {
1416
return _str;
1517
}
1618

1719
private:
18-
const char* _str;
20+
T _str;
1921
};
22+
23+
template <typename String>
24+
struct StringTraits<RawJsonString<String>, void> {
25+
static bool is_null(RawJsonString<String> source) {
26+
return StringTraits<String>::is_null(static_cast<String>(source));
27+
}
28+
29+
typedef RawJsonString<const char*> duplicate_t;
30+
31+
template <typename Buffer>
32+
static duplicate_t duplicate(RawJsonString<String> source, Buffer* buffer) {
33+
return duplicate_t(StringTraits<String>::duplicate(source, buffer));
34+
}
35+
36+
static const bool has_append = false;
37+
static const bool has_equals = false;
38+
static const bool should_duplicate = StringTraits<String>::should_duplicate;
39+
};
40+
}
41+
42+
template <typename T>
43+
inline Internals::RawJsonString<T> RawJson(T str) {
44+
return Internals::RawJsonString<T>(str);
45+
}
2046
}

src/ArduinoJson/Serialization/JsonPrintable.hpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ template <typename T>
2929
class JsonPrintable {
3030
public:
3131
template <typename Print>
32-
typename TypeTraits::EnableIf<!TypeTraits::IsString<Print>::value,
33-
size_t>::type
32+
typename TypeTraits::EnableIf<!StringTraits<Print>::has_append, size_t>::type
3433
printTo(Print &print) const {
3534
JsonWriter<Print> writer(print);
3635
JsonSerializer<JsonWriter<Print> >::serialize(downcast(), writer);
@@ -79,8 +78,7 @@ class JsonPrintable {
7978
}
8079

8180
template <typename Print>
82-
typename TypeTraits::EnableIf<!TypeTraits::IsString<Print>::value,
83-
size_t>::type
81+
typename TypeTraits::EnableIf<!StringTraits<Print>::has_append, size_t>::type
8482
prettyPrintTo(Print &print) const {
8583
IndentedPrint<Print> indentedPrint(print);
8684
return prettyPrintTo(indentedPrint);

src/ArduinoJson/StringTraits/ArduinoStream.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ struct ArduinoStreamTraits {
4343
return c;
4444
}
4545
};
46+
47+
static const bool has_append = false;
48+
static const bool has_equals = false;
4649
};
4750

4851
template <typename TStream>

src/ArduinoJson/StringTraits/CharPointer.hpp

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,58 +33,31 @@ struct CharPointerTraits {
3333
return strcmp(reinterpret_cast<const char*>(str), expected) == 0;
3434
}
3535

36-
// TODO: remove
36+
static bool is_null(const TChar* str) {
37+
return !str;
38+
}
39+
40+
typedef const char* duplicate_t;
41+
3742
template <typename Buffer>
38-
static char* duplicate(const TChar* str, Buffer* buffer) {
43+
static duplicate_t duplicate(const TChar* str, Buffer* buffer) {
3944
if (!str) return NULL;
4045
size_t size = strlen(reinterpret_cast<const char*>(str)) + 1;
4146
void* dup = buffer->alloc(size);
4247
if (dup != NULL) memcpy(dup, str, size);
43-
return static_cast<char*>(dup);
48+
return static_cast<duplicate_t>(dup);
4449
}
4550

4651
static const bool has_append = false;
4752
static const bool has_equals = true;
48-
};
49-
50-
// const char*, const unsigned char*, const signed char*
51-
template <typename TChar>
52-
struct StringTraits<TChar*, typename TypeTraits::EnableIf<
53-
TypeTraits::IsChar<TChar>::value &&
54-
TypeTraits::IsConst<TChar>::value>::type>
55-
: CharPointerTraits<TChar> {
56-
// Just save the pointer
57-
template <typename Buffer, typename Destination>
58-
static typename TypeTraits::EnableIf<TypeTraits::IsConst<TChar>::value,
59-
bool>::type
60-
save(const TChar* source, Destination& dest, Buffer*) {
61-
dest = reinterpret_cast<const char*>(source);
62-
return true;
63-
}
53+
static const bool should_duplicate = !TypeTraits::IsConst<TChar>::value;
6454
};
6555

6656
// char*, unsigned char*, signed char*
57+
// const char*, const unsigned char*, const signed char*
6758
template <typename TChar>
6859
struct StringTraits<TChar*, typename TypeTraits::EnableIf<
69-
TypeTraits::IsChar<TChar>::value &&
70-
!TypeTraits::IsConst<TChar>::value>::type>
71-
: CharPointerTraits<TChar> {
72-
// Make a copy of the string
73-
template <typename Buffer, typename Destination>
74-
static typename TypeTraits::EnableIf<!TypeTraits::IsConst<TChar>::value,
75-
bool>::type
76-
save(const TChar* source, Destination& dest, Buffer* buffer) {
77-
if (source) {
78-
size_t size = strlen(reinterpret_cast<const char*>(source)) + 1;
79-
void* dup = buffer->alloc(size);
80-
if (!dup) return false;
81-
memcpy(dup, source, size);
82-
dest = reinterpret_cast<const char*>(dup);
83-
} else {
84-
dest = reinterpret_cast<const char*>(source);
85-
}
86-
return true;
87-
}
88-
};
60+
TypeTraits::IsChar<TChar>::value>::type>
61+
: CharPointerTraits<TChar> {};
8962
}
9063
}

src/ArduinoJson/StringTraits/FlashString.hpp

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,32 +34,24 @@ struct StringTraits<const __FlashStringHelper*, void> {
3434
return strcmp_P(expected, (const char*)str) == 0;
3535
}
3636

37-
// TODO: remove
37+
static bool is_null(const __FlashString 10000 Helper* str) {
38+
return !str;
39+
}
40+
41+
typedef const char* duplicate_t;
42+
3843
template <typename Buffer>
39-
static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) {
44+
static duplicate_t duplicate(const __FlashStringHelper* str, Buffer* buffer) {
4045
if (!str) return NULL;
4146
size_t size = strlen_P((const char*)str) + 1;
4247
void* dup = buffer->alloc(size);
4348
if (dup != NULL) memcpy_P(dup, (const char*)str, size);
44-
return static_cast<char*>(dup);
45-
}
46-
47-
template <typename Buffer, typename Destination>
48-
static bool save(const __FlashStringHelper* source, Destination& dest,
49-
Buffer* buffer) {
50-
if (source) {
51-
size_t size = strlen_P((const char*)source) + 1;
52-
void* dup = buffer->alloc(size);
53-
if (dup != NULL) memcpy_P(dup, (const char*)source, size);
54-
dest = reinterpret_cast<const char*>(dup);
55-
} else {
56-
dest = reinterpret_cast<const char*>(source);
57-
}
58-
return true;
49+
return static_cast<duplicate_t>(dup);
5950
}
6051

6152
static const bool has_append = false;
6253
static const bool has_equals = true;
54+
static const bool should_duplicate = true;
6355
};
6456
}
6557
}

src/ArduinoJson/StringTraits/StdStream.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ struct StdStreamTraits {
4242
return _stream.eof() ? '\0' : static_cast<char>(_stream.get());
4343
}
4444
};
45+
46+
static const bool has_append = false;
47+
static const bool has_equals = false;
4548
};
4649

4750
template <typename TStream>

src/ArduinoJson/StringTraits/StdString.hpp

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,20 @@ namespace Internals {
1919

2020
template <typename TString>
2121
struct StdStringTraits {
22-
// TODO: remove
22+
typedef const char* duplicate_t;
23+
2324
template <typename Buffer>
24-
static char* duplicate(const TString& str, Buffer* buffer) {
25+
static duplicate_t duplicate(const TString& str, Buffer* buffer) {
2526
if (!str.c_str()) return NULL; // <- Arduino string can return NULL
2627
size_t size = str.length() + 1;
2728
void* dup = buffer->alloc(size);
2829
if (dup != NULL) memcpy(dup, str.c_str(), size);
29-
return static_cast<char*>(dup);
30+
return static_cast<duplicate_t>(dup);
3031
}
3132

32-
template <typename Buffer, typename Destination>
33-
static bool save(const TString& str, Destination& dest, Buffer* buffer) {
33+
static bool is_null(const TString& str) {
3434
// Arduino's String::c_str() can return NULL
35-
if (str.c_str()) {
36-
size_t size = str.length() + 1;
37-
void* dup = buffer->alloc(size);
38-
if (!dup) return false;
39-
memcpy(dup, str.c_str(), size);
40-
dest = reinterpret_cast<const char*>(dup);
41-
} else {
42-
dest = str.c_str();
43-
}
44-
return true;
35+
return !str.c_str();
4536
}
4637

4738
struct Reader : CharPointerTraits<char>::Reader {
@@ -62,6 +53,7 @@ struct StdStringTraits {
6253

6354
static const bool has_append = true;
6455
static const bool has_equals = true;
56+
static const bool should_duplicate = true;
6557
};
6658

6759
#if ARDUINOJSON_ENABLE_ARDUINO_STRING

src/ArduinoJson/StringTraits/StringTraits.hpp

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ namespace ArduinoJson {
1616
namespace Internals {
1717

1818
template <typename TString, typename Enable = void>
19-
struct StringTraits {};
19+
struct StringTraits {
20+
static const bool has_append = false;
21+
static const bool has_equals = false;
22+
};
2023

2124
template <typename TString>
2225
struct StringTraits<const TString, void> : StringTraits<TString> {};
@@ -31,18 +34,3 @@ struct StringTraits<TString&, void> : StringTraits<TString> {};
3134
#include "FlashString.hpp"
3235
#include "StdStream.hpp"
3336
#include "StdString.hpp"
34-
35-
namespace ArduinoJson {
36-
namespace TypeTraits {
37-
template <typename T, typename Enable = void>
38-
struct IsString {
39-
static const bool value = false;
40-
};
41-
42-
template <typename T>
43-
struct IsString<T, typename TypeTraits::EnableIf<
44-
Internals::StringTraits<T>::has_equals>::type> {
45-
static const bool value = Internals::StringTraits<T>::has_equals;
46-
};
47-
}
48-
}

0 commit comments

Comments
 (0)
0