[Common] Improve performance of picojson::serialize_str 18/168018/1
authorJakub Skowron <j.skowron@samsung.com>
Tue, 23 Jan 2018 10:29:48 +0000 (11:29 +0100)
committerJakub Skowron <j.skowron@samsung.com>
Tue, 23 Jan 2018 10:29:48 +0000 (11:29 +0100)
Remove snprintf by mapping all C0 control characters
in a static array.

Change-Id: I3c801551845523b8c33d74426cdddc30103d426d
Signed-off-by: Jakub Skowron <j.skowron@samsung.com>
src/common/picojson.h

index 728b63a..44ae543 100644 (file)
@@ -309,27 +309,33 @@ void copy(const std::string& s, Iter oi) {
 
 template <typename Iter>
 void serialize_str(const std::string& s, Iter oi) {
+  // C0 control characters, 00-1F
+  static const char* u_map[] = {
+      "\\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"};
+  // To be sure we could rewrite C1 control characters also (first decode UTF-8, check, then map to
+  // \u sequence), but for now chromium allows C1 in JSON.parse
+
   *oi++ = '"';
   for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
     switch (*i) {
-#define MAP(val, sym) \
-  case val:           \
-    copy(sym, oi);    \
-    break
-      MAP('"', "\\\"");
-      MAP('\\', "\\\\");
-      MAP('/', "\\/");
-      MAP('\b', "\\b");
-      MAP('\f', "\\f");
-      MAP('\n', "\\n");
-      MAP('\r', "\\r");
-      MAP('\t', "\\t");
-#undef MAP
+      case '"':
+        copy("\\\"", oi);
+        break;
+      case '\\':
+        copy("\\\\", oi);
+        break;
+      case '\x7f':
+        copy("\\u007f", oi);
+        break;
       default:
-        if ((unsigned char)*i < 0x20 || *i == 0x7f) {
-          char buf[7];
-          SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff);
-          copy(buf, buf + 6, oi);
+        if ((unsigned char)*i < 0x20) {
+          const char* u = u_map[(unsigned char)*i];
+          while (*u) {
+            *oi++ = *u++;
+          }
         } else {
           *oi++ = *i;
         }