Skip to content

Commit

Permalink
JSON requires escaped control characters
Browse files Browse the repository at this point in the history
  • Loading branch information
mikee47 committed Aug 15, 2024
1 parent 07bc412 commit ed32ec6
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
98 changes: 98 additions & 0 deletions Sming/Core/Data/Format/Formatter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* Formatter.cpp
*
* @author mikee47 <[email protected]> Aug 2024
*
****/

#include "Formatter.h"

namespace
{
/**
* @brief Get character used for standard escapes
* @param c Code to be escaped
* @retval char Corresponding character, NUL if there isn't a standard escape
*/
char escapeChar(char c)
{
switch(c) {
case '\0':
return '0';
case '\'':
return '\'';
case '\"':
return '"';
case '\?':
return '?';
case '\\':
return '\\';
case '\a':
return 'a';
case '\b':
return 'b';
case '\f':
return 'f';
case '\n':
return 'n';
case '\r':
return 'r';
case '\t':
return 't';
case '\v':
return 'v';
default:
return '\0';
}
}

} // namespace

namespace Format
{
unsigned escapeControls(String& value)
{
// Count number of extra characters we'll need to insert
unsigned extra{0};
for(auto& c : value) {
if(escapeChar(c)) {
extra += 1; // "\"
} else if(c < 0x20) {
extra += 3; // "\xnn"
}
}
if(extra == 0) {
return 0;
}
auto len = value.length();
if(!value.setLength(len + extra)) {
return 0;
}
char* out = value.begin();
const char* in = out;
memmove(out + extra, in, len);
in += extra;
while(len--) {
auto c = *in++;
auto esc = escapeChar(c);
if(esc) {
*out++ = '\\';
*out++ = esc;
} else if(c < 0x20) {
*out++ = '\\';
*out++ = 'x';
*out++ = hexchar(uint8_t(c) >> 4);
*out++ = hexchar(uint8_t(c) & 0x0f);
} else {
*out++ = c;
}
}
return extra;
}

} // namespace Format
7 changes: 7 additions & 0 deletions Sming/Core/Data/Format/Formatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@

namespace Format
{
/**
* @brief Escape standard control codes such as `\n` (below ASCII 0x20)
* @param value String to be modified
* @retval unsigned Number of control characters found and replaced
*/
unsigned escapeControls(String& value);

/**
* @brief Virtual class to perform format-specific String adjustments
*/
Expand Down
1 change: 1 addition & 0 deletions Sming/Core/Data/Format/Json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ bool IsValidUtf8(const char* str, unsigned length)
*/
void Json::escape(String& value) const
{
escapeControls(value);
if(!IsValidUtf8(value.c_str(), value.length())) {
debug_w("Invalid UTF8: %s", value.c_str());
for(unsigned i = 0; i < value.length(); ++i) {
Expand Down

0 comments on commit ed32ec6

Please sign in to comment.