[Pkg-bitcoin-commits] [libunivalue] 60/76: Escape all control characters
Jonas Smedegaard
dr at jones.dk
Mon Apr 4 09:18:33 UTC 2016
This is an automated email from the git hooks/post-receive script.
js pushed a commit to branch master
in repository libunivalue.
commit 33391915429e51477e4ca6e6601b8a539ad96481
Author: Wladimir J. van der Laan <laanwj at gmail.com>
Date: Thu Nov 5 21:39:51 2015 +0100
Escape all control characters
All control characters (U+0000..U+001f) should be escaped according to
RFC4627.
Also escape `U+007f DELETE` - is not mentioned in RFC4627 as a control
character, but it is helpful to escape it as many fonts don't render it,
or weirdly.
---
gen/gen.cpp | 14 ++++++++++---
lib/univalue_escapes.h | 56 +++++++++++++++++++++++++-------------------------
lib/univalue_write.cpp | 4 ++--
test/round1.json | 1 +
test/unitester.cpp | 15 +++++++++++++-
5 files changed, 56 insertions(+), 34 deletions(-)
diff --git a/gen/gen.cpp b/gen/gen.cpp
index 5e5a4d4..4d24bbe 100644
--- a/gen/gen.cpp
+++ b/gen/gen.cpp
@@ -16,10 +16,17 @@
using namespace std;
static bool initEscapes;
-static const char *escapes[256];
+static std::string escapes[256];
static void initJsonEscape()
{
+ // Escape all lower control characters (some get overridden with smaller sequences below)
+ for (int ch=0x00; ch<0x20; ++ch) {
+ char tmpbuf[20];
+ snprintf(tmpbuf, sizeof(tmpbuf), "\\u%04x", ch);
+ escapes[ch] = std::string(tmpbuf);
+ }
+
escapes[(int)'"'] = "\\\"";
escapes[(int)'\\'] = "\\\\";
escapes[(int)'\b'] = "\\b";
@@ -27,6 +34,7 @@ static void initJsonEscape()
escapes[(int)'\n'] = "\\n";
escapes[(int)'\r'] = "\\r";
escapes[(int)'\t'] = "\\t";
+ escapes[(int)'\x7f'] = "\\u007f"; // U+007F DELETE
initEscapes = true;
}
@@ -39,13 +47,13 @@ static void outputEscape()
"static const char *escapes[256] = {\n");
for (unsigned int i = 0; i < 256; i++) {
- if (!escapes[i]) {
+ if (escapes[i].empty()) {
printf("\tNULL,\n");
} else {
printf("\t\"");
unsigned int si;
- for (si = 0; si < strlen(escapes[i]); si++) {
+ for (si = 0; si < escapes[i].size(); si++) {
char ch = escapes[i][si];
switch (ch) {
case '"':
diff --git a/lib/univalue_escapes.h b/lib/univalue_escapes.h
index 4133b24..74596aa 100644
--- a/lib/univalue_escapes.h
+++ b/lib/univalue_escapes.h
@@ -2,38 +2,38 @@
#ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H
#define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H
static const char *escapes[256] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
+ "\\u0000",
+ "\\u0001",
+ "\\u0002",
+ "\\u0003",
+ "\\u0004",
+ "\\u0005",
+ "\\u0006",
+ "\\u0007",
"\\b",
"\\t",
"\\n",
- NULL,
+ "\\u000b",
"\\f",
"\\r",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
+ "\\u000e",
+ "\\u000f",
+ "\\u0010",
+ "\\u0011",
+ "\\u0012",
+ "\\u0013",
+ "\\u0014",
+ "\\u0015",
+ "\\u0016",
+ "\\u0017",
+ "\\u0018",
+ "\\u0019",
+ "\\u001a",
+ "\\u001b",
+ "\\u001c",
+ "\\u001d",
+ "\\u001e",
+ "\\u001f",
NULL,
NULL,
"\\\"",
@@ -129,7 +129,7 @@ static const char *escapes[256] = {
NULL,
NULL,
NULL,
- NULL,
+ "\\u007f",
NULL,
NULL,
NULL,
diff --git a/lib/univalue_write.cpp b/lib/univalue_write.cpp
index bce3997..8076ed3 100644
--- a/lib/univalue_write.cpp
+++ b/lib/univalue_write.cpp
@@ -25,10 +25,10 @@ static string json_escape(const string& inS)
if (escStr)
outS += escStr;
- else if (isprint(ch))
+ else if (ch < 0x80)
outS += ch;
- else {
+ else { // TODO handle UTF-8 properly
char tmpesc[16];
sprintf(tmpesc, "\\u%04x", ch);
outS += tmpesc;
diff --git a/test/round1.json b/test/round1.json
new file mode 100644
index 0000000..a711e73
--- /dev/null
+++ b/test/round1.json
@@ -0,0 +1 @@
+["\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007f"]
diff --git a/test/unitester.cpp b/test/unitester.cpp
index 835556e..c87b86a 100644
--- a/test/unitester.cpp
+++ b/test/unitester.cpp
@@ -20,14 +20,21 @@
using namespace std;
string srcdir(JSON_TEST_SRC);
+static std::string rtrim(std::string s)
+{
+ s.erase(s.find_last_not_of(" \n\r\t")+1);
+ return s;
+}
+
static void runtest(string filename, const string& jdata)
{
fprintf(stderr, "test %s\n", filename.c_str());
string prefix = filename.substr(0, 4);
- bool wantPass = (prefix == "pass");
+ bool wantPass = (prefix == "pass") || (prefix == "roun");
bool wantFail = (prefix == "fail");
+ bool wantRoundTrip = (prefix == "roun");
assert(wantPass || wantFail);
UniValue val;
@@ -38,6 +45,11 @@ static void runtest(string filename, const string& jdata)
} else {
assert(testResult == false);
}
+
+ if (wantRoundTrip) {
+ std::string odata = val.write(0, 0);
+ assert(odata == rtrim(jdata));
+ }
}
static void runtest_file(const char *filename_)
@@ -102,6 +114,7 @@ static const char *filenames[] = {
"pass1.json",
"pass2.json",
"pass3.json",
+ "round1.json", // round-trip test
};
int main (int argc, char *argv[])
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-bitcoin/libunivalue.git
More information about the Pkg-bitcoin-commits
mailing list